Merge branch '2.0.x' into 2.1.x
Closes gh-17078
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -45,8 +45,8 @@ public class RabbitHealthIndicator extends AbstractHealthIndicator {
|
||||
}
|
||||
|
||||
private String getVersion() {
|
||||
return this.rabbitTemplate.execute((channel) -> channel.getConnection()
|
||||
.getServerProperties().get("version").toString());
|
||||
return this.rabbitTemplate
|
||||
.execute((channel) -> channel.getConnection().getServerProperties().get("version").toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -81,8 +81,7 @@ public class AuditEvent implements Serializable {
|
||||
* @param type the event type
|
||||
* @param data the event data
|
||||
*/
|
||||
public AuditEvent(Instant timestamp, String principal, String type,
|
||||
Map<String, Object> data) {
|
||||
public AuditEvent(Instant timestamp, String principal, String type, Map<String, Object> data) {
|
||||
Assert.notNull(timestamp, "Timestamp must not be null");
|
||||
Assert.notNull(type, "Type must not be null");
|
||||
this.timestamp = timestamp;
|
||||
@@ -140,8 +139,8 @@ public class AuditEvent implements Serializable {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AuditEvent [timestamp=" + this.timestamp + ", principal=" + this.principal
|
||||
+ ", type=" + this.type + ", data=" + this.data + "]";
|
||||
return "AuditEvent [timestamp=" + this.timestamp + ", principal=" + this.principal + ", type=" + this.type
|
||||
+ ", data=" + this.data + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -42,10 +42,9 @@ public class AuditEventsEndpoint {
|
||||
}
|
||||
|
||||
@ReadOperation
|
||||
public AuditEventsDescriptor events(@Nullable String principal,
|
||||
@Nullable OffsetDateTime after, @Nullable String type) {
|
||||
List<AuditEvent> events = this.auditEventRepository.find(principal,
|
||||
getInstant(after), type);
|
||||
public AuditEventsDescriptor events(@Nullable String principal, @Nullable OffsetDateTime after,
|
||||
@Nullable String type) {
|
||||
List<AuditEvent> events = this.auditEventRepository.find(principal, getInstant(after), type);
|
||||
return new AuditEventsDescriptor(events);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -83,8 +83,7 @@ public class InMemoryAuditEventRepository implements AuditEventRepository {
|
||||
return events;
|
||||
}
|
||||
|
||||
private boolean isMatch(String principal, Instant after, String type,
|
||||
AuditEvent event) {
|
||||
private boolean isMatch(String principal, Instant after, String type, AuditEvent event) {
|
||||
boolean match = true;
|
||||
match = match && (principal == null || event.getPrincipal().equals(principal));
|
||||
match = match && (after == null || event.getTimestamp().isAfter(after));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -25,8 +25,7 @@ import org.springframework.context.ApplicationListener;
|
||||
* @author Vedran Pavic
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public abstract class AbstractAuditListener
|
||||
implements ApplicationListener<AuditApplicationEvent> {
|
||||
public abstract class AbstractAuditListener implements ApplicationListener<AuditApplicationEvent> {
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(AuditApplicationEvent event) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -40,8 +40,7 @@ public class AuditApplicationEvent extends ApplicationEvent {
|
||||
* @param data the event data
|
||||
* @see AuditEvent#AuditEvent(String, String, Map)
|
||||
*/
|
||||
public AuditApplicationEvent(String principal, String type,
|
||||
Map<String, Object> data) {
|
||||
public AuditApplicationEvent(String principal, String type, Map<String, Object> data) {
|
||||
this(new AuditEvent(principal, type, data));
|
||||
}
|
||||
|
||||
@@ -66,8 +65,7 @@ public class AuditApplicationEvent extends ApplicationEvent {
|
||||
* @param data the event data
|
||||
* @see AuditEvent#AuditEvent(Instant, String, String, Map)
|
||||
*/
|
||||
public AuditApplicationEvent(Instant timestamp, String principal, String type,
|
||||
Map<String, Object> data) {
|
||||
public AuditApplicationEvent(Instant timestamp, String principal, String type, Map<String, Object> data) {
|
||||
this(new AuditEvent(timestamp, principal, type, data));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -62,8 +62,7 @@ public class BeansEndpoint {
|
||||
return new ApplicationBeans(contexts);
|
||||
}
|
||||
|
||||
private static ConfigurableApplicationContext getConfigurableParent(
|
||||
ConfigurableApplicationContext context) {
|
||||
private static ConfigurableApplicationContext getConfigurableParent(ConfigurableApplicationContext context) {
|
||||
ApplicationContext parent = context.getParent();
|
||||
if (parent instanceof ConfigurableApplicationContext) {
|
||||
return (ConfigurableApplicationContext) parent;
|
||||
@@ -117,12 +116,10 @@ public class BeansEndpoint {
|
||||
return null;
|
||||
}
|
||||
ConfigurableApplicationContext parent = getConfigurableParent(context);
|
||||
return new ContextBeans(describeBeans(context.getBeanFactory()),
|
||||
(parent != null) ? parent.getId() : null);
|
||||
return new ContextBeans(describeBeans(context.getBeanFactory()), (parent != null) ? parent.getId() : null);
|
||||
}
|
||||
|
||||
private static Map<String, BeanDescriptor> describeBeans(
|
||||
ConfigurableListableBeanFactory beanFactory) {
|
||||
private static Map<String, BeanDescriptor> describeBeans(ConfigurableListableBeanFactory beanFactory) {
|
||||
Map<String, BeanDescriptor> beans = new HashMap<>();
|
||||
for (String beanName : beanFactory.getBeanDefinitionNames()) {
|
||||
BeanDefinition definition = beanFactory.getBeanDefinition(beanName);
|
||||
@@ -135,13 +132,11 @@ public class BeansEndpoint {
|
||||
|
||||
private static BeanDescriptor describeBean(String name, BeanDefinition definition,
|
||||
ConfigurableListableBeanFactory factory) {
|
||||
return new BeanDescriptor(factory.getAliases(name), definition.getScope(),
|
||||
factory.getType(name), definition.getResourceDescription(),
|
||||
factory.getDependenciesForBean(name));
|
||||
return new BeanDescriptor(factory.getAliases(name), definition.getScope(), factory.getType(name),
|
||||
definition.getResourceDescription(), factory.getDependenciesForBean(name));
|
||||
}
|
||||
|
||||
private static boolean isBeanEligible(String beanName, BeanDefinition bd,
|
||||
ConfigurableBeanFactory bf) {
|
||||
private static boolean isBeanEligible(String beanName, BeanDefinition bd, ConfigurableBeanFactory bf) {
|
||||
return (bd.getRole() != BeanDefinition.ROLE_INFRASTRUCTURE
|
||||
&& (!bd.isLazyInit() || bf.containsSingleton(beanName)));
|
||||
}
|
||||
@@ -164,11 +159,9 @@ public class BeansEndpoint {
|
||||
|
||||
private final String[] dependencies;
|
||||
|
||||
private BeanDescriptor(String[] aliases, String scope, Class<?> type,
|
||||
String resource, String[] dependencies) {
|
||||
private BeanDescriptor(String[] aliases, String scope, Class<?> type, String resource, String[] dependencies) {
|
||||
this.aliases = aliases;
|
||||
this.scope = (StringUtils.hasText(scope) ? scope
|
||||
: BeanDefinition.SCOPE_SINGLETON);
|
||||
this.scope = (StringUtils.hasText(scope) ? scope : BeanDefinition.SCOPE_SINGLETON);
|
||||
this.type = type;
|
||||
this.resource = resource;
|
||||
this.dependencies = dependencies;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -61,14 +61,12 @@ public class CachesEndpoint {
|
||||
getCacheEntries(matchAll(), matchAll()).forEach((entry) -> {
|
||||
String cacheName = entry.getName();
|
||||
String cacheManager = entry.getCacheManager();
|
||||
Map<String, CacheDescriptor> cacheManagerDescriptors = descriptors
|
||||
.computeIfAbsent(cacheManager, (key) -> new LinkedHashMap<>());
|
||||
cacheManagerDescriptors.put(cacheName,
|
||||
new CacheDescriptor(entry.getTarget()));
|
||||
Map<String, CacheDescriptor> cacheManagerDescriptors = descriptors.computeIfAbsent(cacheManager,
|
||||
(key) -> new LinkedHashMap<>());
|
||||
cacheManagerDescriptors.put(cacheName, new CacheDescriptor(entry.getTarget()));
|
||||
});
|
||||
Map<String, CacheManagerDescriptor> cacheManagerDescriptors = new LinkedHashMap<>();
|
||||
descriptors.forEach((name, entries) -> cacheManagerDescriptors.put(name,
|
||||
new CacheManagerDescriptor(entries)));
|
||||
descriptors.forEach((name, entries) -> cacheManagerDescriptors.put(name, new CacheManagerDescriptor(entries)));
|
||||
return new CachesReport(cacheManagerDescriptors);
|
||||
}
|
||||
|
||||
@@ -82,8 +80,7 @@ public class CachesEndpoint {
|
||||
*/
|
||||
@ReadOperation
|
||||
public CacheEntry cache(@Selector String cache, @Nullable String cacheManager) {
|
||||
return extractUniqueCacheEntry(cache,
|
||||
getCacheEntries((name) -> name.equals(cache), isNameMatch(cacheManager)));
|
||||
return extractUniqueCacheEntry(cache, getCacheEntries((name) -> name.equals(cache), isNameMatch(cacheManager)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,25 +110,21 @@ public class CachesEndpoint {
|
||||
private List<CacheEntry> getCacheEntries(Predicate<String> cacheNamePredicate,
|
||||
Predicate<String> cacheManagerNamePredicate) {
|
||||
return this.cacheManagers.keySet().stream().filter(cacheManagerNamePredicate)
|
||||
.flatMap((cacheManagerName) -> getCacheEntries(cacheManagerName,
|
||||
cacheNamePredicate).stream())
|
||||
.flatMap((cacheManagerName) -> getCacheEntries(cacheManagerName, cacheNamePredicate).stream())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<CacheEntry> getCacheEntries(String cacheManagerName,
|
||||
Predicate<String> cacheNamePredicate) {
|
||||
private List<CacheEntry> getCacheEntries(String cacheManagerName, Predicate<String> cacheNamePredicate) {
|
||||
CacheManager cacheManager = this.cacheManagers.get(cacheManagerName);
|
||||
return cacheManager.getCacheNames().stream().filter(cacheNamePredicate)
|
||||
.map(cacheManager::getCache).filter(Objects::nonNull)
|
||||
.map((cache) -> new CacheEntry(cache, cacheManagerName))
|
||||
return cacheManager.getCacheNames().stream().filter(cacheNamePredicate).map(cacheManager::getCache)
|
||||
.filter(Objects::nonNull).map((cache) -> new CacheEntry(cache, cacheManagerName))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private CacheEntry extractUniqueCacheEntry(String cache, List<CacheEntry> entries) {
|
||||
if (entries.size() > 1) {
|
||||
throw new NonUniqueCacheException(cache,
|
||||
entries.stream().map(CacheEntry::getCacheManager).distinct()
|
||||
.collect(Collectors.toList()));
|
||||
entries.stream().map(CacheEntry::getCacheManager).distinct().collect(Collectors.toList()));
|
||||
}
|
||||
return (!entries.isEmpty() ? entries.get(0) : null);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -40,12 +40,10 @@ public class CachesEndpointWebExtension {
|
||||
}
|
||||
|
||||
@ReadOperation
|
||||
public WebEndpointResponse<CacheEntry> cache(@Selector String cache,
|
||||
@Nullable String cacheManager) {
|
||||
public WebEndpointResponse<CacheEntry> cache(@Selector String cache, @Nullable String cacheManager) {
|
||||
try {
|
||||
CacheEntry entry = this.delegate.cache(cache, cacheManager);
|
||||
int status = (entry != null) ? WebEndpointResponse.STATUS_OK
|
||||
: WebEndpointResponse.STATUS_NOT_FOUND;
|
||||
int status = (entry != null) ? WebEndpointResponse.STATUS_OK : WebEndpointResponse.STATUS_NOT_FOUND;
|
||||
return new WebEndpointResponse<>(entry, status);
|
||||
}
|
||||
catch (NonUniqueCacheException ex) {
|
||||
@@ -54,12 +52,10 @@ public class CachesEndpointWebExtension {
|
||||
}
|
||||
|
||||
@DeleteOperation
|
||||
public WebEndpointResponse<Void> clearCache(@Selector String cache,
|
||||
@Nullable String cacheManager) {
|
||||
public WebEndpointResponse<Void> clearCache(@Selector String cache, @Nullable String cacheManager) {
|
||||
try {
|
||||
boolean cleared = this.delegate.clearCache(cache, cacheManager);
|
||||
int status = (cleared ? WebEndpointResponse.STATUS_NO_CONTENT
|
||||
: WebEndpointResponse.STATUS_NOT_FOUND);
|
||||
int status = (cleared ? WebEndpointResponse.STATUS_NO_CONTENT : WebEndpointResponse.STATUS_NOT_FOUND);
|
||||
return new WebEndpointResponse<>(status);
|
||||
}
|
||||
catch (NonUniqueCacheException ex) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -31,10 +31,9 @@ public class NonUniqueCacheException extends RuntimeException {
|
||||
|
||||
private final Collection<String> cacheManagerNames;
|
||||
|
||||
public NonUniqueCacheException(String cacheName,
|
||||
Collection<String> cacheManagerNames) {
|
||||
super(String.format("Multiple caches named %s found, specify the 'cacheManager' "
|
||||
+ "to use: %s", cacheName, cacheManagerNames));
|
||||
public NonUniqueCacheException(String cacheName, Collection<String> cacheManagerNames) {
|
||||
super(String.format("Multiple caches named %s found, specify the 'cacheManager' " + "to use: %s", cacheName,
|
||||
cacheManagerNames));
|
||||
this.cacheName = cacheName;
|
||||
this.cacheManagerNames = Collections.unmodifiableCollection(cacheManagerNames);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -54,8 +54,7 @@ public class CassandraHealthIndicator extends AbstractHealthIndicator {
|
||||
@Override
|
||||
protected void doHealthCheck(Health.Builder builder) throws Exception {
|
||||
Select select = QueryBuilder.select("release_version").from("system", "local");
|
||||
ResultSet results = this.cassandraOperations.getCqlOperations()
|
||||
.queryForResultSet(select);
|
||||
ResultSet results = this.cassandraOperations.getCqlOperations().queryForResultSet(select);
|
||||
if (results.isExhausted()) {
|
||||
builder.up();
|
||||
return;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -39,20 +39,16 @@ public class CassandraReactiveHealthIndicator extends AbstractReactiveHealthIndi
|
||||
* Create a new {@link CassandraHealthIndicator} instance.
|
||||
* @param reactiveCassandraOperations the Cassandra operations
|
||||
*/
|
||||
public CassandraReactiveHealthIndicator(
|
||||
ReactiveCassandraOperations reactiveCassandraOperations) {
|
||||
Assert.notNull(reactiveCassandraOperations,
|
||||
"ReactiveCassandraOperations must not be null");
|
||||
public CassandraReactiveHealthIndicator(ReactiveCassandraOperations reactiveCassandraOperations) {
|
||||
Assert.notNull(reactiveCassandraOperations, "ReactiveCassandraOperations must not be null");
|
||||
this.reactiveCassandraOperations = reactiveCassandraOperations;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Mono<Health> doHealthCheck(Health.Builder builder) {
|
||||
Select select = QueryBuilder.select("release_version").from("system", "local");
|
||||
return this.reactiveCassandraOperations.getReactiveCqlOperations()
|
||||
.queryForObject(select, String.class)
|
||||
.map((version) -> builder.up().withDetail("version", version).build())
|
||||
.single();
|
||||
return this.reactiveCassandraOperations.getReactiveCqlOperations().queryForObject(select, String.class)
|
||||
.map((version) -> builder.up().withDetail("version", version).build()).single();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -38,12 +38,10 @@ import org.springframework.context.ConfigurableApplicationContext;
|
||||
public class ShutdownEndpoint implements ApplicationContextAware {
|
||||
|
||||
private static final Map<String, String> NO_CONTEXT_MESSAGE = Collections
|
||||
.unmodifiableMap(
|
||||
Collections.singletonMap("message", "No context to shutdown."));
|
||||
.unmodifiableMap(Collections.singletonMap("message", "No context to shutdown."));
|
||||
|
||||
private static final Map<String, String> SHUTDOWN_MESSAGE = Collections
|
||||
.unmodifiableMap(
|
||||
Collections.singletonMap("message", "Shutting down, bye..."));
|
||||
.unmodifiableMap(Collections.singletonMap("message", "Shutting down, bye..."));
|
||||
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -99,31 +99,27 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
|
||||
Map<String, ContextConfigurationProperties> contextProperties = new HashMap<>();
|
||||
ApplicationContext target = context;
|
||||
while (target != null) {
|
||||
contextProperties.put(target.getId(),
|
||||
describeConfigurationProperties(target, getObjectMapper()));
|
||||
contextProperties.put(target.getId(), describeConfigurationProperties(target, getObjectMapper()));
|
||||
target = target.getParent();
|
||||
}
|
||||
return new ApplicationConfigurationProperties(contextProperties);
|
||||
}
|
||||
|
||||
private ContextConfigurationProperties describeConfigurationProperties(
|
||||
ApplicationContext context, ObjectMapper mapper) {
|
||||
ConfigurationBeanFactoryMetadata beanFactoryMetadata = getBeanFactoryMetadata(
|
||||
context);
|
||||
Map<String, Object> beans = getConfigurationPropertiesBeans(context,
|
||||
beanFactoryMetadata);
|
||||
private ContextConfigurationProperties describeConfigurationProperties(ApplicationContext context,
|
||||
ObjectMapper mapper) {
|
||||
ConfigurationBeanFactoryMetadata beanFactoryMetadata = getBeanFactoryMetadata(context);
|
||||
Map<String, Object> beans = getConfigurationPropertiesBeans(context, beanFactoryMetadata);
|
||||
Map<String, ConfigurationPropertiesBeanDescriptor> beanDescriptors = new HashMap<>();
|
||||
beans.forEach((beanName, bean) -> {
|
||||
String prefix = extractPrefix(context, beanFactoryMetadata, beanName);
|
||||
beanDescriptors.put(beanName, new ConfigurationPropertiesBeanDescriptor(
|
||||
prefix, sanitize(prefix, safeSerialize(mapper, bean, prefix))));
|
||||
beanDescriptors.put(beanName, new ConfigurationPropertiesBeanDescriptor(prefix,
|
||||
sanitize(prefix, safeSerialize(mapper, bean, prefix))));
|
||||
});
|
||||
return new ContextConfigurationProperties(beanDescriptors,
|
||||
(context.getParent() != null) ? context.getParent().getId() : null);
|
||||
}
|
||||
|
||||
private ConfigurationBeanFactoryMetadata getBeanFactoryMetadata(
|
||||
ApplicationContext context) {
|
||||
private ConfigurationBeanFactoryMetadata getBeanFactoryMetadata(ApplicationContext context) {
|
||||
Map<String, ConfigurationBeanFactoryMetadata> beans = context
|
||||
.getBeansOfType(ConfigurationBeanFactoryMetadata.class);
|
||||
if (beans.size() == 1) {
|
||||
@@ -132,14 +128,12 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
|
||||
return null;
|
||||
}
|
||||
|
||||
private Map<String, Object> getConfigurationPropertiesBeans(
|
||||
ApplicationContext context,
|
||||
private Map<String, Object> getConfigurationPropertiesBeans(ApplicationContext context,
|
||||
ConfigurationBeanFactoryMetadata beanFactoryMetadata) {
|
||||
Map<String, Object> beans = new HashMap<>();
|
||||
beans.putAll(context.getBeansWithAnnotation(ConfigurationProperties.class));
|
||||
if (beanFactoryMetadata != null) {
|
||||
beans.putAll(beanFactoryMetadata
|
||||
.getBeansWithFactoryAnnotation(ConfigurationProperties.class));
|
||||
beans.putAll(beanFactoryMetadata.getBeansWithFactoryAnnotation(ConfigurationProperties.class));
|
||||
}
|
||||
return beans;
|
||||
}
|
||||
@@ -153,14 +147,12 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
|
||||
* @return the serialized instance
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, Object> safeSerialize(ObjectMapper mapper, Object bean,
|
||||
String prefix) {
|
||||
private Map<String, Object> safeSerialize(ObjectMapper mapper, Object bean, String prefix) {
|
||||
try {
|
||||
return new HashMap<>(mapper.convertValue(bean, Map.class));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return new HashMap<>(Collections.singletonMap("error",
|
||||
"Cannot serialize '" + prefix + "'"));
|
||||
return new HashMap<>(Collections.singletonMap("error", "Cannot serialize '" + prefix + "'"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,10 +188,9 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
|
||||
}
|
||||
|
||||
private void applyConfigurationPropertiesFilter(ObjectMapper mapper) {
|
||||
mapper.setAnnotationIntrospector(
|
||||
new ConfigurationPropertiesAnnotationIntrospector());
|
||||
mapper.setFilterProvider(new SimpleFilterProvider()
|
||||
.setDefaultFilter(new ConfigurationPropertiesPropertyFilter()));
|
||||
mapper.setAnnotationIntrospector(new ConfigurationPropertiesAnnotationIntrospector());
|
||||
mapper.setFilterProvider(
|
||||
new SimpleFilterProvider().setDefaultFilter(new ConfigurationPropertiesPropertyFilter()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -209,13 +200,12 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
|
||||
* @param beanName the bean name
|
||||
* @return the prefix
|
||||
*/
|
||||
private String extractPrefix(ApplicationContext context,
|
||||
ConfigurationBeanFactoryMetadata beanFactoryMetaData, String beanName) {
|
||||
ConfigurationProperties annotation = context.findAnnotationOnBean(beanName,
|
||||
ConfigurationProperties.class);
|
||||
private String extractPrefix(ApplicationContext context, ConfigurationBeanFactoryMetadata beanFactoryMetaData,
|
||||
String beanName) {
|
||||
ConfigurationProperties annotation = context.findAnnotationOnBean(beanName, ConfigurationProperties.class);
|
||||
if (beanFactoryMetaData != null) {
|
||||
ConfigurationProperties override = beanFactoryMetaData
|
||||
.findFactoryAnnotation(beanName, ConfigurationProperties.class);
|
||||
ConfigurationProperties override = beanFactoryMetaData.findFactoryAnnotation(beanName,
|
||||
ConfigurationProperties.class);
|
||||
if (override != null) {
|
||||
// The @Bean-level @ConfigurationProperties overrides the one at type
|
||||
// level when binding. Arguably we should render them both, but this one
|
||||
@@ -274,8 +264,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
|
||||
* properties.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
private static class ConfigurationPropertiesAnnotationIntrospector
|
||||
extends JacksonAnnotationIntrospector {
|
||||
private static class ConfigurationPropertiesAnnotationIntrospector extends JacksonAnnotationIntrospector {
|
||||
|
||||
@Override
|
||||
public Object findFilterId(Annotated a) {
|
||||
@@ -298,11 +287,9 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
|
||||
* <li>Properties that throw an exception when retrieving their value.
|
||||
* </ul>
|
||||
*/
|
||||
private static class ConfigurationPropertiesPropertyFilter
|
||||
extends SimpleBeanPropertyFilter {
|
||||
private static class ConfigurationPropertiesPropertyFilter extends SimpleBeanPropertyFilter {
|
||||
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(ConfigurationPropertiesPropertyFilter.class);
|
||||
private static final Log logger = LogFactory.getLog(ConfigurationPropertiesPropertyFilter.class);
|
||||
|
||||
@Override
|
||||
protected boolean include(BeanPropertyWriter writer) {
|
||||
@@ -319,14 +306,13 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeAsField(Object pojo, JsonGenerator jgen,
|
||||
SerializerProvider provider, PropertyWriter writer) throws Exception {
|
||||
public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider provider,
|
||||
PropertyWriter writer) throws Exception {
|
||||
if (writer instanceof BeanPropertyWriter) {
|
||||
try {
|
||||
if (pojo == ((BeanPropertyWriter) writer).get(pojo)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Skipping '" + writer.getFullName() + "' on '"
|
||||
+ pojo.getClass().getName()
|
||||
logger.debug("Skipping '" + writer.getFullName() + "' on '" + pojo.getClass().getName()
|
||||
+ "' as it is self-referential");
|
||||
}
|
||||
return;
|
||||
@@ -334,9 +320,8 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Skipping '" + writer.getFullName() + "' on '"
|
||||
+ pojo.getClass().getName() + "' as an exception "
|
||||
+ "was thrown when retrieving its value", ex);
|
||||
logger.debug("Skipping '" + writer.getFullName() + "' on '" + pojo.getClass().getName()
|
||||
+ "' as an exception " + "was thrown when retrieving its value", ex);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -352,8 +337,8 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
|
||||
protected static class GenericSerializerModifier extends BeanSerializerModifier {
|
||||
|
||||
@Override
|
||||
public List<BeanPropertyWriter> changeProperties(SerializationConfig config,
|
||||
BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
|
||||
public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc,
|
||||
List<BeanPropertyWriter> beanProperties) {
|
||||
List<BeanPropertyWriter> result = new ArrayList<>();
|
||||
for (BeanPropertyWriter writer : beanProperties) {
|
||||
boolean readable = isReadable(beanDesc, writer);
|
||||
@@ -374,15 +359,11 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
|
||||
// should be kosher. Lists and Maps are also auto-detected by default since
|
||||
// that's what the metadata generator does. This filter is not used if there
|
||||
// is JSON metadata for the property, so it's mainly for user-defined beans.
|
||||
return (setter != null)
|
||||
|| ClassUtils.getPackageName(parentType)
|
||||
.equals(ClassUtils.getPackageName(type))
|
||||
|| Map.class.isAssignableFrom(type)
|
||||
|| Collection.class.isAssignableFrom(type);
|
||||
return (setter != null) || ClassUtils.getPackageName(parentType).equals(ClassUtils.getPackageName(type))
|
||||
|| Map.class.isAssignableFrom(type) || Collection.class.isAssignableFrom(type);
|
||||
}
|
||||
|
||||
private AnnotatedMethod findSetter(BeanDescription beanDesc,
|
||||
BeanPropertyWriter writer) {
|
||||
private AnnotatedMethod findSetter(BeanDescription beanDesc, BeanPropertyWriter writer) {
|
||||
String name = "set" + determineAccessorSuffix(writer.getName());
|
||||
Class<?> type = writer.getType().getRawClass();
|
||||
AnnotatedMethod setter = beanDesc.findMethod(name, new Class<?>[] { type });
|
||||
@@ -402,8 +383,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
|
||||
* @return the accessor suffix for {@code propertyName}
|
||||
*/
|
||||
private String determineAccessorSuffix(String propertyName) {
|
||||
if (propertyName.length() > 1
|
||||
&& Character.isUpperCase(propertyName.charAt(1))) {
|
||||
if (propertyName.length() > 1 && Character.isUpperCase(propertyName.charAt(1))) {
|
||||
return propertyName;
|
||||
}
|
||||
return StringUtils.capitalize(propertyName);
|
||||
@@ -419,8 +399,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
|
||||
|
||||
private final Map<String, ContextConfigurationProperties> contexts;
|
||||
|
||||
private ApplicationConfigurationProperties(
|
||||
Map<String, ContextConfigurationProperties> contexts) {
|
||||
private ApplicationConfigurationProperties(Map<String, ContextConfigurationProperties> contexts) {
|
||||
this.contexts = contexts;
|
||||
}
|
||||
|
||||
@@ -440,8 +419,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
|
||||
|
||||
private final String parentId;
|
||||
|
||||
private ContextConfigurationProperties(
|
||||
Map<String, ConfigurationPropertiesBeanDescriptor> beans,
|
||||
private ContextConfigurationProperties(Map<String, ConfigurationPropertiesBeanDescriptor> beans,
|
||||
String parentId) {
|
||||
this.beans = beans;
|
||||
this.parentId = parentId;
|
||||
@@ -467,8 +445,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
|
||||
|
||||
private final Map<String, Object> properties;
|
||||
|
||||
private ConfigurationPropertiesBeanDescriptor(String prefix,
|
||||
Map<String, Object> properties) {
|
||||
private ConfigurationPropertiesBeanDescriptor(String prefix, Map<String, Object> properties) {
|
||||
this.prefix = prefix;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -42,8 +42,8 @@ class CouchbaseHealth {
|
||||
void applyTo(Builder builder) {
|
||||
builder = isCouchbaseUp(this.diagnostics) ? builder.up() : builder.down();
|
||||
builder.withDetail("sdk", this.diagnostics.sdk());
|
||||
builder.withDetail("endpoints", this.diagnostics.endpoints().stream()
|
||||
.map(this::describe).collect(Collectors.toList()));
|
||||
builder.withDetail("endpoints",
|
||||
this.diagnostics.endpoints().stream().map(this::describe).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
private boolean isCouchbaseUp(DiagnosticsReport diagnostics) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -52,10 +52,8 @@ public class ElasticsearchHealthIndicator extends AbstractHealthIndicator {
|
||||
* @param responseTimeout the request timeout in milliseconds
|
||||
* @param indices the indices to check
|
||||
*/
|
||||
public ElasticsearchHealthIndicator(Client client, long responseTimeout,
|
||||
List<String> indices) {
|
||||
this(client, responseTimeout,
|
||||
(indices != null) ? StringUtils.toStringArray(indices) : null);
|
||||
public ElasticsearchHealthIndicator(Client client, long responseTimeout, List<String> indices) {
|
||||
this(client, responseTimeout, (indices != null) ? StringUtils.toStringArray(indices) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,8 +62,7 @@ public class ElasticsearchHealthIndicator extends AbstractHealthIndicator {
|
||||
* @param responseTimeout the request timeout in milliseconds
|
||||
* @param indices the indices to check
|
||||
*/
|
||||
public ElasticsearchHealthIndicator(Client client, long responseTimeout,
|
||||
String... indices) {
|
||||
public ElasticsearchHealthIndicator(Client client, long responseTimeout, String... indices) {
|
||||
super("Elasticsearch health check failed");
|
||||
this.client = client;
|
||||
this.responseTimeout = responseTimeout;
|
||||
@@ -74,10 +71,9 @@ public class ElasticsearchHealthIndicator extends AbstractHealthIndicator {
|
||||
|
||||
@Override
|
||||
protected void doHealthCheck(Health.Builder builder) throws Exception {
|
||||
ClusterHealthRequest request = Requests.clusterHealthRequest(
|
||||
ObjectUtils.isEmpty(this.indices) ? ALL_INDICES : this.indices);
|
||||
ClusterHealthResponse response = this.client.admin().cluster().health(request)
|
||||
.actionGet(this.responseTimeout);
|
||||
ClusterHealthRequest request = Requests
|
||||
.clusterHealthRequest(ObjectUtils.isEmpty(this.indices) ? ALL_INDICES : this.indices);
|
||||
ClusterHealthResponse response = this.client.admin().cluster().health(request).actionGet(this.responseTimeout);
|
||||
switch (response.getStatus()) {
|
||||
case GREEN:
|
||||
case YELLOW:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -48,15 +48,13 @@ public class ElasticsearchJestHealthIndicator extends AbstractHealthIndicator {
|
||||
|
||||
@Override
|
||||
protected void doHealthCheck(Health.Builder builder) throws Exception {
|
||||
JestResult healthResult = this.jestClient
|
||||
.execute(new io.searchbox.cluster.Health.Builder().build());
|
||||
JestResult healthResult = this.jestClient.execute(new io.searchbox.cluster.Health.Builder().build());
|
||||
if (healthResult.getResponseCode() != 200 || !healthResult.isSucceeded()) {
|
||||
builder.down();
|
||||
builder.withDetail("statusCode", healthResult.getResponseCode());
|
||||
}
|
||||
else {
|
||||
Map<String, Object> response = this.jsonParser
|
||||
.parseMap(healthResult.getJsonString());
|
||||
Map<String, Object> response = this.jsonParser.parseMap(healthResult.getJsonString());
|
||||
String status = (String) response.get("status");
|
||||
if (status.equals(io.searchbox.cluster.Health.Status.RED.getKey())) {
|
||||
builder.outOfService();
|
||||
|
||||
@@ -57,8 +57,7 @@ public class ElasticsearchRestHealthIndicator extends AbstractHealthIndicator {
|
||||
|
||||
@Override
|
||||
protected void doHealthCheck(Health.Builder builder) throws Exception {
|
||||
Response response = this.client
|
||||
.performRequest(new Request("GET", "/_cluster/health/"));
|
||||
Response response = this.client.performRequest(new Request("GET", "/_cluster/health/"));
|
||||
StatusLine statusLine = response.getStatusLine();
|
||||
if (statusLine.getStatusCode() != HttpStatus.SC_OK) {
|
||||
builder.down();
|
||||
@@ -67,8 +66,7 @@ public class ElasticsearchRestHealthIndicator extends AbstractHealthIndicator {
|
||||
return;
|
||||
}
|
||||
try (InputStream inputStream = response.getEntity().getContent()) {
|
||||
doHealthCheck(builder,
|
||||
StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8));
|
||||
doHealthCheck(builder, StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -30,8 +30,7 @@ import org.springframework.util.Assert;
|
||||
* @author Phillip Webb
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public abstract class AbstractExposableEndpoint<O extends Operation>
|
||||
implements ExposableEndpoint<O> {
|
||||
public abstract class AbstractExposableEndpoint<O extends Operation> implements ExposableEndpoint<O> {
|
||||
|
||||
private final EndpointId id;
|
||||
|
||||
@@ -45,8 +44,7 @@ public abstract class AbstractExposableEndpoint<O extends Operation>
|
||||
* @param enabledByDefault if the endpoint is enabled by default
|
||||
* @param operations the endpoint operations
|
||||
*/
|
||||
public AbstractExposableEndpoint(EndpointId id, boolean enabledByDefault,
|
||||
Collection<? extends O> operations) {
|
||||
public AbstractExposableEndpoint(EndpointId id, boolean enabledByDefault, Collection<? extends O> operations) {
|
||||
Assert.notNull(id, "ID must not be null");
|
||||
Assert.notNull(operations, "Operations must not be null");
|
||||
this.id = id;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -52,12 +52,9 @@ public final class EndpointId {
|
||||
|
||||
private EndpointId(String value) {
|
||||
Assert.hasText(value, "Value must not be empty");
|
||||
Assert.isTrue(VALID_PATTERN.matcher(value).matches(),
|
||||
"Value must only contain valid chars");
|
||||
Assert.isTrue(!Character.isDigit(value.charAt(0)),
|
||||
"Value must not start with a number");
|
||||
Assert.isTrue(!Character.isUpperCase(value.charAt(0)),
|
||||
"Value must not start with an uppercase letter");
|
||||
Assert.isTrue(VALID_PATTERN.matcher(value).matches(), "Value must only contain valid chars");
|
||||
Assert.isTrue(!Character.isDigit(value.charAt(0)), "Value must not start with a number");
|
||||
Assert.isTrue(!Character.isUpperCase(value.charAt(0)), "Value must not start with an uppercase letter");
|
||||
if (WARNING_PATTERN.matcher(value).find()) {
|
||||
logWarning(value);
|
||||
}
|
||||
@@ -85,8 +82,7 @@ public final class EndpointId {
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
return this.lowerCaseAlphaNumeric
|
||||
.equals(((EndpointId) obj).lowerCaseAlphaNumeric);
|
||||
return this.lowerCaseAlphaNumeric.equals(((EndpointId) obj).lowerCaseAlphaNumeric);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -132,8 +128,7 @@ public final class EndpointId {
|
||||
|
||||
private static void logWarning(String value) {
|
||||
if (logger.isWarnEnabled() && loggedWarnings.add(value)) {
|
||||
logger.warn("Endpoint ID '" + value
|
||||
+ "' contains invalid characters, please migrate to a valid format.");
|
||||
logger.warn("Endpoint ID '" + value + "' contains invalid characters, please migrate to a valid format.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -31,8 +31,7 @@ public class InvalidEndpointRequestException extends RuntimeException {
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public InvalidEndpointRequestException(String message, String reason,
|
||||
Throwable cause) {
|
||||
public InvalidEndpointRequestException(String message, String reason, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -39,8 +39,7 @@ public class InvocationContext {
|
||||
* @param securityContext the current security context. Never {@code null}
|
||||
* @param arguments the arguments available to the operation. Never {@code null}
|
||||
*/
|
||||
public InvocationContext(SecurityContext securityContext,
|
||||
Map<String, Object> arguments) {
|
||||
public InvocationContext(SecurityContext securityContext, Map<String, Object> arguments) {
|
||||
Assert.notNull(securityContext, "SecurityContext must not be null");
|
||||
Assert.notNull(arguments, "Arguments must not be null");
|
||||
this.securityContext = securityContext;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -38,8 +38,7 @@ public class Sanitizer {
|
||||
private Pattern[] keysToSanitize;
|
||||
|
||||
public Sanitizer() {
|
||||
this("password", "secret", "key", "token", ".*credentials.*", "vcap_services",
|
||||
"sun.java.command");
|
||||
this("password", "secret", "key", "token", ".*credentials.*", "vcap_services", "sun.java.command");
|
||||
}
|
||||
|
||||
public Sanitizer(String... keysToSanitize) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -33,8 +33,8 @@ import org.springframework.util.Assert;
|
||||
* @author Phillip Webb
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public abstract class AbstractDiscoveredEndpoint<O extends Operation>
|
||||
extends AbstractExposableEndpoint<O> implements DiscoveredEndpoint<O> {
|
||||
public abstract class AbstractDiscoveredEndpoint<O extends Operation> extends AbstractExposableEndpoint<O>
|
||||
implements DiscoveredEndpoint<O> {
|
||||
|
||||
private final EndpointDiscoverer<?, ?> discoverer;
|
||||
|
||||
@@ -48,9 +48,8 @@ public abstract class AbstractDiscoveredEndpoint<O extends Operation>
|
||||
* @param enabledByDefault if the endpoint is enabled by default
|
||||
* @param operations the endpoint operations
|
||||
*/
|
||||
public AbstractDiscoveredEndpoint(EndpointDiscoverer<?, ?> discoverer,
|
||||
Object endpointBean, EndpointId id, boolean enabledByDefault,
|
||||
Collection<? extends O> operations) {
|
||||
public AbstractDiscoveredEndpoint(EndpointDiscoverer<?, ?> discoverer, Object endpointBean, EndpointId id,
|
||||
boolean enabledByDefault, Collection<? extends O> operations) {
|
||||
super(id, enabledByDefault, operations);
|
||||
Assert.notNull(discoverer, "Discoverer must not be null");
|
||||
Assert.notNull(endpointBean, "EndpointBean must not be null");
|
||||
@@ -70,8 +69,7 @@ public abstract class AbstractDiscoveredEndpoint<O extends Operation>
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
ToStringCreator creator = new ToStringCreator(this)
|
||||
.append("discoverer", this.discoverer.getClass().getName())
|
||||
ToStringCreator creator = new ToStringCreator(this).append("discoverer", this.discoverer.getClass().getName())
|
||||
.append("endpointBean", this.endpointBean.getClass().getName());
|
||||
appendFields(creator);
|
||||
return creator.toString();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -41,8 +41,7 @@ public abstract class AbstractDiscoveredOperation implements Operation {
|
||||
* @param operationMethod the method backing the operation
|
||||
* @param invoker the operation invoker to use
|
||||
*/
|
||||
public AbstractDiscoveredOperation(DiscoveredOperationMethod operationMethod,
|
||||
OperationInvoker invoker) {
|
||||
public AbstractDiscoveredOperation(DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
|
||||
this.operationMethod = operationMethod;
|
||||
this.invoker = invoker;
|
||||
}
|
||||
@@ -63,8 +62,7 @@ public abstract class AbstractDiscoveredOperation implements Operation {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
ToStringCreator creator = new ToStringCreator(this)
|
||||
.append("operationMethod", this.operationMethod)
|
||||
ToStringCreator creator = new ToStringCreator(this).append("operationMethod", this.operationMethod)
|
||||
.append("invoker", this.invoker);
|
||||
appendFields(creator);
|
||||
return creator.toString();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -51,8 +51,7 @@ abstract class DiscoveredOperationsFactory<O extends Operation> {
|
||||
private static final Map<OperationType, Class<? extends Annotation>> OPERATION_TYPES;
|
||||
|
||||
static {
|
||||
Map<OperationType, Class<? extends Annotation>> operationTypes = new EnumMap<>(
|
||||
OperationType.class);
|
||||
Map<OperationType, Class<? extends Annotation>> operationTypes = new EnumMap<>(OperationType.class);
|
||||
operationTypes.put(OperationType.READ, ReadOperation.class);
|
||||
operationTypes.put(OperationType.WRITE, WriteOperation.class);
|
||||
operationTypes.put(OperationType.DELETE, DeleteOperation.class);
|
||||
@@ -70,45 +69,43 @@ abstract class DiscoveredOperationsFactory<O extends Operation> {
|
||||
}
|
||||
|
||||
public Collection<O> createOperations(EndpointId id, Object target) {
|
||||
return MethodIntrospector.selectMethods(target.getClass(),
|
||||
(MetadataLookup<O>) (method) -> createOperation(id, target, method))
|
||||
return MethodIntrospector
|
||||
.selectMethods(target.getClass(), (MetadataLookup<O>) (method) -> createOperation(id, target, method))
|
||||
.values();
|
||||
}
|
||||
|
||||
private O createOperation(EndpointId endpointId, Object target, Method method) {
|
||||
return OPERATION_TYPES.entrySet().stream()
|
||||
.map((entry) -> createOperation(endpointId, target, method,
|
||||
entry.getKey(), entry.getValue()))
|
||||
.map((entry) -> createOperation(endpointId, target, method, entry.getKey(), entry.getValue()))
|
||||
.filter(Objects::nonNull).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
private O createOperation(EndpointId endpointId, Object target, Method method,
|
||||
OperationType operationType, Class<? extends Annotation> annotationType) {
|
||||
AnnotationAttributes annotationAttributes = AnnotatedElementUtils
|
||||
.getMergedAnnotationAttributes(method, annotationType);
|
||||
private O createOperation(EndpointId endpointId, Object target, Method method, OperationType operationType,
|
||||
Class<? extends Annotation> annotationType) {
|
||||
AnnotationAttributes annotationAttributes = AnnotatedElementUtils.getMergedAnnotationAttributes(method,
|
||||
annotationType);
|
||||
if (annotationAttributes == null) {
|
||||
return null;
|
||||
}
|
||||
DiscoveredOperationMethod operationMethod = new DiscoveredOperationMethod(method,
|
||||
operationType, annotationAttributes);
|
||||
OperationInvoker invoker = new ReflectiveOperationInvoker(target, operationMethod,
|
||||
this.parameterValueMapper);
|
||||
DiscoveredOperationMethod operationMethod = new DiscoveredOperationMethod(method, operationType,
|
||||
annotationAttributes);
|
||||
OperationInvoker invoker = new ReflectiveOperationInvoker(target, operationMethod, this.parameterValueMapper);
|
||||
invoker = applyAdvisors(endpointId, operationMethod, invoker);
|
||||
return createOperation(endpointId, operationMethod, invoker);
|
||||
}
|
||||
|
||||
private OperationInvoker applyAdvisors(EndpointId endpointId,
|
||||
OperationMethod operationMethod, OperationInvoker invoker) {
|
||||
private OperationInvoker applyAdvisors(EndpointId endpointId, OperationMethod operationMethod,
|
||||
OperationInvoker invoker) {
|
||||
if (this.invokerAdvisors != null) {
|
||||
for (OperationInvokerAdvisor advisor : this.invokerAdvisors) {
|
||||
invoker = advisor.apply(endpointId, operationMethod.getOperationType(),
|
||||
operationMethod.getParameters(), invoker);
|
||||
invoker = advisor.apply(endpointId, operationMethod.getOperationType(), operationMethod.getParameters(),
|
||||
invoker);
|
||||
}
|
||||
}
|
||||
return invoker;
|
||||
}
|
||||
|
||||
protected abstract O createOperation(EndpointId endpointId,
|
||||
DiscoveredOperationMethod operationMethod, OperationInvoker invoker);
|
||||
protected abstract O createOperation(EndpointId endpointId, DiscoveredOperationMethod operationMethod,
|
||||
OperationInvoker invoker);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -25,8 +25,7 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public abstract class DiscovererEndpointFilter
|
||||
implements EndpointFilter<DiscoveredEndpoint<?>> {
|
||||
public abstract class DiscovererEndpointFilter implements EndpointFilter<DiscoveredEndpoint<?>> {
|
||||
|
||||
private final Class<? extends EndpointDiscoverer<?, ?>> discoverer;
|
||||
|
||||
@@ -34,8 +33,7 @@ public abstract class DiscovererEndpointFilter
|
||||
* Create a new {@link DiscovererEndpointFilter} instance.
|
||||
* @param discoverer the required discoverer
|
||||
*/
|
||||
protected DiscovererEndpointFilter(
|
||||
Class<? extends EndpointDiscoverer<?, ?>> discoverer) {
|
||||
protected DiscovererEndpointFilter(Class<? extends EndpointDiscoverer<?, ?>> discoverer) {
|
||||
Assert.notNull(discoverer, "Discoverer must not be null");
|
||||
this.discoverer = discoverer;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -84,30 +84,25 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
|
||||
* @param invokerAdvisors invoker advisors to apply
|
||||
* @param filters filters to apply
|
||||
*/
|
||||
public EndpointDiscoverer(ApplicationContext applicationContext,
|
||||
ParameterValueMapper parameterValueMapper,
|
||||
Collection<OperationInvokerAdvisor> invokerAdvisors,
|
||||
Collection<EndpointFilter<E>> filters) {
|
||||
public EndpointDiscoverer(ApplicationContext applicationContext, ParameterValueMapper parameterValueMapper,
|
||||
Collection<OperationInvokerAdvisor> invokerAdvisors, Collection<EndpointFilter<E>> filters) {
|
||||
Assert.notNull(applicationContext, "ApplicationContext must not be null");
|
||||
Assert.notNull(parameterValueMapper, "ParameterValueMapper must not be null");
|
||||
Assert.notNull(invokerAdvisors, "InvokerAdvisors must not be null");
|
||||
Assert.notNull(filters, "Filters must not be null");
|
||||
this.applicationContext = applicationContext;
|
||||
this.filters = Collections.unmodifiableCollection(filters);
|
||||
this.operationsFactory = getOperationsFactory(parameterValueMapper,
|
||||
invokerAdvisors);
|
||||
this.operationsFactory = getOperationsFactory(parameterValueMapper, invokerAdvisors);
|
||||
}
|
||||
|
||||
private DiscoveredOperationsFactory<O> getOperationsFactory(
|
||||
ParameterValueMapper parameterValueMapper,
|
||||
private DiscoveredOperationsFactory<O> getOperationsFactory(ParameterValueMapper parameterValueMapper,
|
||||
Collection<OperationInvokerAdvisor> invokerAdvisors) {
|
||||
return new DiscoveredOperationsFactory<O>(parameterValueMapper, invokerAdvisors) {
|
||||
|
||||
@Override
|
||||
protected O createOperation(EndpointId endpointId,
|
||||
DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
|
||||
return EndpointDiscoverer.this.createOperation(endpointId,
|
||||
operationMethod, invoker);
|
||||
protected O createOperation(EndpointId endpointId, DiscoveredOperationMethod operationMethod,
|
||||
OperationInvoker invoker) {
|
||||
return EndpointDiscoverer.this.createOperation(endpointId, operationMethod, invoker);
|
||||
}
|
||||
|
||||
};
|
||||
@@ -129,17 +124,14 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
|
||||
|
||||
private Collection<EndpointBean> createEndpointBeans() {
|
||||
Map<EndpointId, EndpointBean> byId = new LinkedHashMap<>();
|
||||
String[] beanNames = BeanFactoryUtils.beanNamesForAnnotationIncludingAncestors(
|
||||
this.applicationContext, Endpoint.class);
|
||||
String[] beanNames = BeanFactoryUtils.beanNamesForAnnotationIncludingAncestors(this.applicationContext,
|
||||
Endpoint.class);
|
||||
for (String beanName : beanNames) {
|
||||
if (!ScopedProxyUtils.isScopedTarget(beanName)) {
|
||||
EndpointBean endpointBean = createEndpointBean(beanName);
|
||||
EndpointBean previous = byId.putIfAbsent(endpointBean.getId(),
|
||||
endpointBean);
|
||||
Assert.state(previous == null,
|
||||
() -> "Found two endpoints with the id '" + endpointBean.getId()
|
||||
+ "': '" + endpointBean.getBeanName() + "' and '"
|
||||
+ previous.getBeanName() + "'");
|
||||
EndpointBean previous = byId.putIfAbsent(endpointBean.getId(), endpointBean);
|
||||
Assert.state(previous == null, () -> "Found two endpoints with the id '" + endpointBean.getId() + "': '"
|
||||
+ endpointBean.getBeanName() + "' and '" + previous.getBeanName() + "'");
|
||||
}
|
||||
}
|
||||
return byId.values();
|
||||
@@ -153,15 +145,13 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
|
||||
private void addExtensionBeans(Collection<EndpointBean> endpointBeans) {
|
||||
Map<EndpointId, EndpointBean> byId = endpointBeans.stream()
|
||||
.collect(Collectors.toMap(EndpointBean::getId, Function.identity()));
|
||||
String[] beanNames = BeanFactoryUtils.beanNamesForAnnotationIncludingAncestors(
|
||||
this.applicationContext, EndpointExtension.class);
|
||||
String[] beanNames = BeanFactoryUtils.beanNamesForAnnotationIncludingAncestors(this.applicationContext,
|
||||
EndpointExtension.class);
|
||||
for (String beanName : beanNames) {
|
||||
ExtensionBean extensionBean = createExtensionBean(beanName);
|
||||
EndpointBean endpointBean = byId.get(extensionBean.getEndpointId());
|
||||
Assert.state(endpointBean != null,
|
||||
() -> ("Invalid extension '" + extensionBean.getBeanName()
|
||||
+ "': no endpoint found with id '"
|
||||
+ extensionBean.getEndpointId() + "'"));
|
||||
Assert.state(endpointBean != null, () -> ("Invalid extension '" + extensionBean.getBeanName()
|
||||
+ "': no endpoint found with id '" + extensionBean.getEndpointId() + "'"));
|
||||
addExtensionBean(endpointBean, extensionBean);
|
||||
}
|
||||
}
|
||||
@@ -171,13 +161,10 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
|
||||
return new ExtensionBean(beanName, bean);
|
||||
}
|
||||
|
||||
private void addExtensionBean(EndpointBean endpointBean,
|
||||
ExtensionBean extensionBean) {
|
||||
private void addExtensionBean(EndpointBean endpointBean, ExtensionBean extensionBean) {
|
||||
if (isExtensionExposed(endpointBean, extensionBean)) {
|
||||
Assert.state(
|
||||
isEndpointExposed(endpointBean) || isEndpointFiltered(endpointBean),
|
||||
() -> "Endpoint bean '" + endpointBean.getBeanName()
|
||||
+ "' cannot support the extension bean '"
|
||||
Assert.state(isEndpointExposed(endpointBean) || isEndpointFiltered(endpointBean),
|
||||
() -> "Endpoint bean '" + endpointBean.getBeanName() + "' cannot support the extension bean '"
|
||||
+ extensionBean.getBeanName() + "'");
|
||||
endpointBean.addExtension(extensionBean);
|
||||
}
|
||||
@@ -198,25 +185,22 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
|
||||
EndpointId id = endpointBean.getId();
|
||||
addOperations(indexed, id, endpointBean.getBean(), false);
|
||||
if (endpointBean.getExtensions().size() > 1) {
|
||||
String extensionBeans = endpointBean.getExtensions().stream()
|
||||
.map(ExtensionBean::getBeanName).collect(Collectors.joining(", "));
|
||||
throw new IllegalStateException(
|
||||
"Found multiple extensions for the endpoint bean "
|
||||
+ endpointBean.getBeanName() + " (" + extensionBeans + ")");
|
||||
String extensionBeans = endpointBean.getExtensions().stream().map(ExtensionBean::getBeanName)
|
||||
.collect(Collectors.joining(", "));
|
||||
throw new IllegalStateException("Found multiple extensions for the endpoint bean "
|
||||
+ endpointBean.getBeanName() + " (" + extensionBeans + ")");
|
||||
}
|
||||
for (ExtensionBean extensionBean : endpointBean.getExtensions()) {
|
||||
addOperations(indexed, id, extensionBean.getBean(), true);
|
||||
}
|
||||
assertNoDuplicateOperations(endpointBean, indexed);
|
||||
List<O> operations = indexed.values().stream().map(this::getLast)
|
||||
.filter(Objects::nonNull).collect(Collectors.collectingAndThen(
|
||||
Collectors.toList(), Collections::unmodifiableList));
|
||||
return createEndpoint(endpointBean.getBean(), id,
|
||||
endpointBean.isEnabledByDefault(), operations);
|
||||
List<O> operations = indexed.values().stream().map(this::getLast).filter(Objects::nonNull)
|
||||
.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
|
||||
return createEndpoint(endpointBean.getBean(), id, endpointBean.isEnabledByDefault(), operations);
|
||||
}
|
||||
|
||||
private void addOperations(MultiValueMap<OperationKey, O> indexed, EndpointId id,
|
||||
Object target, boolean replaceLast) {
|
||||
private void addOperations(MultiValueMap<OperationKey, O> indexed, EndpointId id, Object target,
|
||||
boolean replaceLast) {
|
||||
Set<OperationKey> replacedLast = new HashSet<>();
|
||||
Collection<O> operations = this.operationsFactory.createOperations(id, target);
|
||||
for (O operation : operations) {
|
||||
@@ -233,27 +217,21 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
|
||||
return CollectionUtils.isEmpty(list) ? null : list.get(list.size() - 1);
|
||||
}
|
||||
|
||||
private void assertNoDuplicateOperations(EndpointBean endpointBean,
|
||||
MultiValueMap<OperationKey, O> indexed) {
|
||||
List<OperationKey> duplicates = indexed.entrySet().stream()
|
||||
.filter((entry) -> entry.getValue().size() > 1).map(Map.Entry::getKey)
|
||||
.collect(Collectors.toList());
|
||||
private void assertNoDuplicateOperations(EndpointBean endpointBean, MultiValueMap<OperationKey, O> indexed) {
|
||||
List<OperationKey> duplicates = indexed.entrySet().stream().filter((entry) -> entry.getValue().size() > 1)
|
||||
.map(Map.Entry::getKey).collect(Collectors.toList());
|
||||
if (!duplicates.isEmpty()) {
|
||||
Set<ExtensionBean> extensions = endpointBean.getExtensions();
|
||||
String extensionBeanNames = extensions.stream()
|
||||
.map(ExtensionBean::getBeanName).collect(Collectors.joining(", "));
|
||||
throw new IllegalStateException(
|
||||
"Unable to map duplicate endpoint operations: "
|
||||
+ duplicates.toString() + " to " + endpointBean.getBeanName()
|
||||
+ (extensions.isEmpty() ? ""
|
||||
: " (" + extensionBeanNames + ")"));
|
||||
String extensionBeanNames = extensions.stream().map(ExtensionBean::getBeanName)
|
||||
.collect(Collectors.joining(", "));
|
||||
throw new IllegalStateException("Unable to map duplicate endpoint operations: " + duplicates.toString()
|
||||
+ " to " + endpointBean.getBeanName()
|
||||
+ (extensions.isEmpty() ? "" : " (" + extensionBeanNames + ")"));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isExtensionExposed(EndpointBean endpointBean,
|
||||
ExtensionBean extensionBean) {
|
||||
return isFilterMatch(extensionBean.getFilter(), endpointBean)
|
||||
&& isExtensionExposed(extensionBean.getBean());
|
||||
private boolean isExtensionExposed(EndpointBean endpointBean, ExtensionBean extensionBean) {
|
||||
return isFilterMatch(extensionBean.getFilter(), endpointBean) && isExtensionExposed(extensionBean.getBean());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -267,8 +245,7 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
|
||||
}
|
||||
|
||||
private boolean isEndpointExposed(EndpointBean endpointBean) {
|
||||
return isFilterMatch(endpointBean.getFilter(), endpointBean)
|
||||
&& !isEndpointFiltered(endpointBean)
|
||||
return isFilterMatch(endpointBean.getFilter(), endpointBean) && !isEndpointFiltered(endpointBean)
|
||||
&& isEndpointExposed(endpointBean.getBean());
|
||||
}
|
||||
|
||||
@@ -300,11 +277,9 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
|
||||
return true;
|
||||
}
|
||||
E endpoint = getFilterEndpoint(endpointBean);
|
||||
Class<?> generic = ResolvableType.forClass(EndpointFilter.class, filter)
|
||||
.resolveGeneric(0);
|
||||
Class<?> generic = ResolvableType.forClass(EndpointFilter.class, filter).resolveGeneric(0);
|
||||
if (generic == null || generic.isInstance(endpoint)) {
|
||||
EndpointFilter<E> instance = (EndpointFilter<E>) BeanUtils
|
||||
.instantiateClass(filter);
|
||||
EndpointFilter<E> instance = (EndpointFilter<E>) BeanUtils.instantiateClass(filter);
|
||||
return isFilterMatch(instance, endpoint);
|
||||
}
|
||||
return false;
|
||||
@@ -317,16 +292,15 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private boolean isFilterMatch(EndpointFilter<E> filter, E endpoint) {
|
||||
return LambdaSafe.callback(EndpointFilter.class, filter, endpoint)
|
||||
.withLogger(EndpointDiscoverer.class).invokeAnd((f) -> f.match(endpoint))
|
||||
.get();
|
||||
return LambdaSafe.callback(EndpointFilter.class, filter, endpoint).withLogger(EndpointDiscoverer.class)
|
||||
.invokeAnd((f) -> f.match(endpoint)).get();
|
||||
}
|
||||
|
||||
private E getFilterEndpoint(EndpointBean endpointBean) {
|
||||
E endpoint = this.filterEndpoints.get(endpointBean);
|
||||
if (endpoint == null) {
|
||||
endpoint = createEndpoint(endpointBean.getBean(), endpointBean.getId(),
|
||||
endpointBean.isEnabledByDefault(), Collections.emptySet());
|
||||
endpoint = createEndpoint(endpointBean.getBean(), endpointBean.getId(), endpointBean.isEnabledByDefault(),
|
||||
Collections.emptySet());
|
||||
this.filterEndpoints.put(endpointBean, endpoint);
|
||||
}
|
||||
return endpoint;
|
||||
@@ -334,8 +308,7 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Class<? extends E> getEndpointType() {
|
||||
return (Class<? extends E>) ResolvableType
|
||||
.forClass(EndpointDiscoverer.class, getClass()).resolveGeneric(0);
|
||||
return (Class<? extends E>) ResolvableType.forClass(EndpointDiscoverer.class, getClass()).resolveGeneric(0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -346,8 +319,8 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
|
||||
* @param operations the endpoint operations
|
||||
* @return a created endpoint (a {@link DiscoveredEndpoint} is recommended)
|
||||
*/
|
||||
protected abstract E createEndpoint(Object endpointBean, EndpointId id,
|
||||
boolean enabledByDefault, Collection<O> operations);
|
||||
protected abstract E createEndpoint(Object endpointBean, EndpointId id, boolean enabledByDefault,
|
||||
Collection<O> operations);
|
||||
|
||||
/**
|
||||
* Factory method to create an {@link Operation endpoint operation}.
|
||||
@@ -356,8 +329,8 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
|
||||
* @param invoker the invoker to use
|
||||
* @return a created operation
|
||||
*/
|
||||
protected abstract O createOperation(EndpointId endpointId,
|
||||
DiscoveredOperationMethod operationMethod, OperationInvoker invoker);
|
||||
protected abstract O createOperation(EndpointId endpointId, DiscoveredOperationMethod operationMethod,
|
||||
OperationInvoker invoker);
|
||||
|
||||
/**
|
||||
* Create an {@link OperationKey} for the given operation.
|
||||
@@ -429,13 +402,11 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
|
||||
private Set<ExtensionBean> extensions = new LinkedHashSet<>();
|
||||
|
||||
EndpointBean(String beanName, Object bean) {
|
||||
AnnotationAttributes attributes = AnnotatedElementUtils
|
||||
.findMergedAnnotationAttributes(bean.getClass(), Endpoint.class, true,
|
||||
true);
|
||||
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(bean.getClass(),
|
||||
Endpoint.class, true, true);
|
||||
String id = attributes.getString("id");
|
||||
Assert.state(StringUtils.hasText(id),
|
||||
() -> "No @Endpoint id attribute specified for "
|
||||
+ bean.getClass().getName());
|
||||
() -> "No @Endpoint id attribute specified for " + bean.getClass().getName());
|
||||
this.beanName = beanName;
|
||||
this.bean = bean;
|
||||
this.id = EndpointId.of(id);
|
||||
@@ -452,8 +423,8 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
|
||||
}
|
||||
|
||||
private Class<?> getFilter(Class<?> type) {
|
||||
AnnotationAttributes attributes = AnnotatedElementUtils
|
||||
.getMergedAnnotationAttributes(type, FilteredEndpoint.class);
|
||||
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(type,
|
||||
FilteredEndpoint.class);
|
||||
if (attributes == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -498,15 +469,13 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
|
||||
ExtensionBean(String beanName, Object bean) {
|
||||
this.bean = bean;
|
||||
this.beanName = beanName;
|
||||
AnnotationAttributes attributes = AnnotatedElementUtils
|
||||
.getMergedAnnotationAttributes(bean.getClass(),
|
||||
EndpointExtension.class);
|
||||
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(bean.getClass(),
|
||||
EndpointExtension.class);
|
||||
Class<?> endpointType = attributes.getClass("endpoint");
|
||||
AnnotationAttributes endpointAttributes = AnnotatedElementUtils
|
||||
.findMergedAnnotationAttributes(endpointType, Endpoint.class, true,
|
||||
true);
|
||||
Assert.state(endpointAttributes != null, () -> "Extension "
|
||||
+ endpointType.getName() + " does not specify an endpoint");
|
||||
AnnotationAttributes endpointAttributes = AnnotatedElementUtils.findMergedAnnotationAttributes(endpointType,
|
||||
Endpoint.class, true, true);
|
||||
Assert.state(endpointAttributes != null,
|
||||
() -> "Extension " + endpointType.getName() + " does not specify an endpoint");
|
||||
this.endpointId = EndpointId.of(endpointAttributes.getString("id"));
|
||||
this.filter = attributes.getClass("filter");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -35,12 +35,10 @@ public final class MissingParametersException extends InvalidEndpointRequestExce
|
||||
private final Set<OperationParameter> missingParameters;
|
||||
|
||||
public MissingParametersException(Set<OperationParameter> missingParameters) {
|
||||
super("Failed to invoke operation because the following required "
|
||||
+ "parameters were missing: "
|
||||
super("Failed to invoke operation because the following required " + "parameters were missing: "
|
||||
+ StringUtils.collectionToCommaDelimitedString(missingParameters),
|
||||
"Missing parameters: "
|
||||
+ missingParameters.stream().map(OperationParameter::getName)
|
||||
.collect(Collectors.joining(",")));
|
||||
+ missingParameters.stream().map(OperationParameter::getName).collect(Collectors.joining(",")));
|
||||
this.missingParameters = missingParameters;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -36,7 +36,7 @@ public interface OperationInvokerAdvisor {
|
||||
* @param invoker the invoker to advise
|
||||
* @return an potentially new operation invoker with support for additional features
|
||||
*/
|
||||
OperationInvoker apply(EndpointId endpointId, OperationType operationType,
|
||||
OperationParameters parameters, OperationInvoker invoker);
|
||||
OperationInvoker apply(EndpointId endpointId, OperationType operationType, OperationParameters parameters,
|
||||
OperationInvoker invoker);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -38,10 +38,9 @@ public final class ParameterMappingException extends InvalidEndpointRequestExcep
|
||||
* @param value the value being mapped
|
||||
* @param cause the cause of the mapping failure
|
||||
*/
|
||||
public ParameterMappingException(OperationParameter parameter, Object value,
|
||||
Throwable cause) {
|
||||
super("Failed to map " + value + " of type " + value.getClass() + " to "
|
||||
+ parameter, "Parameter mapping failure", cause);
|
||||
public ParameterMappingException(OperationParameter parameter, Object value, Throwable cause) {
|
||||
super("Failed to map " + value + " of type " + value.getClass() + " to " + parameter,
|
||||
"Parameter mapping failure", cause);
|
||||
this.parameter = parameter;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -37,7 +37,6 @@ public interface ParameterValueMapper {
|
||||
* @return a value suitable for that parameter
|
||||
* @throws ParameterMappingException when a mapping failure occurs
|
||||
*/
|
||||
Object mapParameterValue(OperationParameter parameter, Object value)
|
||||
throws ParameterMappingException;
|
||||
Object mapParameterValue(OperationParameter parameter, Object value) throws ParameterMappingException;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -52,8 +52,7 @@ public class ConversionServiceParameterValueMapper implements ParameterValueMapp
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object mapParameterValue(OperationParameter parameter, Object value)
|
||||
throws ParameterMappingException {
|
||||
public Object mapParameterValue(OperationParameter parameter, Object value) throws ParameterMappingException {
|
||||
try {
|
||||
return this.conversionService.convert(value, parameter.getType());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -52,8 +52,7 @@ public class OperationMethod {
|
||||
Assert.notNull(operationType, "OperationType must not be null");
|
||||
this.method = method;
|
||||
this.operationType = operationType;
|
||||
this.operationParameters = new OperationMethodParameters(method,
|
||||
DEFAULT_PARAMETER_NAME_DISCOVERER);
|
||||
this.operationParameters = new OperationMethodParameters(method, DEFAULT_PARAMETER_NAME_DISCOVERER);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,8 +81,7 @@ public class OperationMethod {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Operation " + this.operationType.name().toLowerCase(Locale.ENGLISH)
|
||||
+ " method " + this.method;
|
||||
return "Operation " + this.operationType.name().toLowerCase(Locale.ENGLISH) + " method " + this.method;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -43,24 +43,19 @@ class OperationMethodParameters implements OperationParameters {
|
||||
* @param method the source method
|
||||
* @param parameterNameDiscoverer the parameter name discoverer
|
||||
*/
|
||||
OperationMethodParameters(Method method,
|
||||
ParameterNameDiscoverer parameterNameDiscoverer) {
|
||||
OperationMethodParameters(Method method, ParameterNameDiscoverer parameterNameDiscoverer) {
|
||||
Assert.notNull(method, "Method must not be null");
|
||||
Assert.notNull(parameterNameDiscoverer,
|
||||
"ParameterNameDiscoverer must not be null");
|
||||
Assert.notNull(parameterNameDiscoverer, "ParameterNameDiscoverer must not be null");
|
||||
String[] parameterNames = parameterNameDiscoverer.getParameterNames(method);
|
||||
Parameter[] parameters = method.getParameters();
|
||||
Assert.state(parameterNames != null,
|
||||
() -> "Failed to extract parameter names for " + method);
|
||||
Assert.state(parameterNames != null, () -> "Failed to extract parameter names for " + method);
|
||||
this.operationParameters = getOperationParameters(parameters, parameterNames);
|
||||
}
|
||||
|
||||
private List<OperationParameter> getOperationParameters(Parameter[] parameters,
|
||||
String[] names) {
|
||||
private List<OperationParameter> getOperationParameters(Parameter[] parameters, String[] names) {
|
||||
List<OperationParameter> operationParameters = new ArrayList<>(parameters.length);
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
operationParameters
|
||||
.add(new OperationMethodParameter(names[i], parameters[i]));
|
||||
operationParameters.add(new OperationMethodParameter(names[i], parameters[i]));
|
||||
}
|
||||
return Collections.unmodifiableList(operationParameters);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -78,8 +78,7 @@ public class ReflectiveOperationInvoker implements OperationInvoker {
|
||||
|
||||
private void validateRequiredParameters(InvocationContext context) {
|
||||
Set<OperationParameter> missing = this.operationMethod.getParameters().stream()
|
||||
.filter((parameter) -> isMissing(context, parameter))
|
||||
.collect(Collectors.toSet());
|
||||
.filter((parameter) -> isMissing(context, parameter)).collect(Collectors.toSet());
|
||||
if (!missing.isEmpty()) {
|
||||
throw new MissingParametersException(missing);
|
||||
}
|
||||
@@ -99,12 +98,11 @@ public class ReflectiveOperationInvoker implements OperationInvoker {
|
||||
}
|
||||
|
||||
private Object[] resolveArguments(InvocationContext context) {
|
||||
return this.operationMethod.getParameters().stream()
|
||||
.map((parameter) -> resolveArgument(parameter, context)).toArray();
|
||||
return this.operationMethod.getParameters().stream().map((parameter) -> resolveArgument(parameter, context))
|
||||
.toArray();
|
||||
}
|
||||
|
||||
private Object resolveArgument(OperationParameter parameter,
|
||||
InvocationContext context) {
|
||||
private Object resolveArgument(OperationParameter parameter, InvocationContext context) {
|
||||
if (Principal.class.equals(parameter.getType())) {
|
||||
return context.getSecurityContext().getPrincipal();
|
||||
}
|
||||
@@ -117,8 +115,8 @@ public class ReflectiveOperationInvoker implements OperationInvoker {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("target", this.target)
|
||||
.append("method", this.operationMethod).toString();
|
||||
return new ToStringCreator(this).append("target", this.target).append("method", this.operationMethod)
|
||||
.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -36,14 +36,13 @@ public class CachingOperationInvokerAdvisor implements OperationInvokerAdvisor {
|
||||
|
||||
private final Function<EndpointId, Long> endpointIdTimeToLive;
|
||||
|
||||
public CachingOperationInvokerAdvisor(
|
||||
Function<EndpointId, Long> endpointIdTimeToLive) {
|
||||
public CachingOperationInvokerAdvisor(Function<EndpointId, Long> endpointIdTimeToLive) {
|
||||
this.endpointIdTimeToLive = endpointIdTimeToLive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OperationInvoker apply(EndpointId endpointId, OperationType operationType,
|
||||
OperationParameters parameters, OperationInvoker invoker) {
|
||||
public OperationInvoker apply(EndpointId endpointId, OperationType operationType, OperationParameters parameters,
|
||||
OperationInvoker invoker) {
|
||||
if (operationType == OperationType.READ && !hasMandatoryParameter(parameters)) {
|
||||
Long timeToLive = this.endpointIdTimeToLive.apply(endpointId);
|
||||
if (timeToLive != null && timeToLive > 0) {
|
||||
@@ -55,8 +54,7 @@ public class CachingOperationInvokerAdvisor implements OperationInvokerAdvisor {
|
||||
|
||||
private boolean hasMandatoryParameter(OperationParameters parameters) {
|
||||
for (OperationParameter parameter : parameters) {
|
||||
if (parameter.isMandatory()
|
||||
&& !SecurityContext.class.isAssignableFrom(parameter.getType())) {
|
||||
if (parameter.isMandatory() && !SecurityContext.class.isAssignableFrom(parameter.getType())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -48,8 +48,8 @@ import org.springframework.util.ClassUtils;
|
||||
*/
|
||||
public class EndpointMBean implements DynamicMBean {
|
||||
|
||||
private static final boolean REACTOR_PRESENT = ClassUtils.isPresent(
|
||||
"reactor.core.publisher.Mono", EndpointMBean.class.getClassLoader());
|
||||
private static final boolean REACTOR_PRESENT = ClassUtils.isPresent("reactor.core.publisher.Mono",
|
||||
EndpointMBean.class.getClassLoader());
|
||||
|
||||
private final JmxOperationResponseMapper responseMapper;
|
||||
|
||||
@@ -61,8 +61,7 @@ public class EndpointMBean implements DynamicMBean {
|
||||
|
||||
private final Map<String, JmxOperation> operations;
|
||||
|
||||
EndpointMBean(JmxOperationResponseMapper responseMapper, ClassLoader classLoader,
|
||||
ExposableJmxEndpoint endpoint) {
|
||||
EndpointMBean(JmxOperationResponseMapper responseMapper, ClassLoader classLoader, ExposableJmxEndpoint endpoint) {
|
||||
Assert.notNull(responseMapper, "ResponseMapper must not be null");
|
||||
Assert.notNull(endpoint, "Endpoint must not be null");
|
||||
this.responseMapper = responseMapper;
|
||||
@@ -74,8 +73,7 @@ public class EndpointMBean implements DynamicMBean {
|
||||
|
||||
private Map<String, JmxOperation> getOperations(ExposableJmxEndpoint endpoint) {
|
||||
Map<String, JmxOperation> operations = new HashMap<>();
|
||||
endpoint.getOperations()
|
||||
.forEach((operation) -> operations.put(operation.getName(), operation));
|
||||
endpoint.getOperations().forEach((operation) -> operations.put(operation.getName(), operation));
|
||||
return Collections.unmodifiableMap(operations);
|
||||
}
|
||||
|
||||
@@ -89,12 +87,11 @@ public class EndpointMBean implements DynamicMBean {
|
||||
throws MBeanException, ReflectionException {
|
||||
JmxOperation operation = this.operations.get(actionName);
|
||||
if (operation == null) {
|
||||
String message = "Endpoint with id '" + this.endpoint.getEndpointId()
|
||||
+ "' has no operation named " + actionName;
|
||||
String message = "Endpoint with id '" + this.endpoint.getEndpointId() + "' has no operation named "
|
||||
+ actionName;
|
||||
throw new ReflectionException(new IllegalArgumentException(message), message);
|
||||
}
|
||||
ClassLoader previousClassLoader = overrideThreadContextClassLoader(
|
||||
this.classLoader);
|
||||
ClassLoader previousClassLoader = overrideThreadContextClassLoader(this.classLoader);
|
||||
try {
|
||||
return invoke(operation, params);
|
||||
}
|
||||
@@ -115,14 +112,12 @@ public class EndpointMBean implements DynamicMBean {
|
||||
return null;
|
||||
}
|
||||
|
||||
private Object invoke(JmxOperation operation, Object[] params)
|
||||
throws MBeanException, ReflectionException {
|
||||
private Object invoke(JmxOperation operation, Object[] params) throws MBeanException, ReflectionException {
|
||||
try {
|
||||
String[] parameterNames = operation.getParameters().stream()
|
||||
.map(JmxOperationParameter::getName).toArray(String[]::new);
|
||||
String[] parameterNames = operation.getParameters().stream().map(JmxOperationParameter::getName)
|
||||
.toArray(String[]::new);
|
||||
Map<String, Object> arguments = getArguments(parameterNames, params);
|
||||
InvocationContext context = new InvocationContext(SecurityContext.NONE,
|
||||
arguments);
|
||||
InvocationContext context = new InvocationContext(SecurityContext.NONE, arguments);
|
||||
Object result = operation.invoke(context);
|
||||
if (REACTOR_PRESENT) {
|
||||
result = ReactiveHandler.handle(result);
|
||||
@@ -130,8 +125,7 @@ public class EndpointMBean implements DynamicMBean {
|
||||
return this.responseMapper.mapResponse(result);
|
||||
}
|
||||
catch (InvalidEndpointRequestException ex) {
|
||||
throw new ReflectionException(new IllegalArgumentException(ex.getMessage()),
|
||||
ex.getMessage());
|
||||
throw new ReflectionException(new IllegalArgumentException(ex.getMessage()), ex.getMessage());
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new MBeanException(translateIfNecessary(ex), ex.getMessage());
|
||||
@@ -160,8 +154,8 @@ public class EndpointMBean implements DynamicMBean {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(Attribute attribute) throws AttributeNotFoundException,
|
||||
InvalidAttributeValueException, MBeanException, ReflectionException {
|
||||
public void setAttribute(Attribute attribute)
|
||||
throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
|
||||
throw new AttributeNotFoundException("EndpointMBeans do not support attributes");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -35,7 +35,6 @@ public interface EndpointObjectNameFactory {
|
||||
* @return the {@link ObjectName} to use for the endpoint
|
||||
* @throws MalformedObjectNameException if the object name is invalid
|
||||
*/
|
||||
ObjectName getObjectName(ExposableJmxEndpoint endpoint)
|
||||
throws MalformedObjectNameException;
|
||||
ObjectName getObjectName(ExposableJmxEndpoint endpoint) throws MalformedObjectNameException;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -40,10 +40,9 @@ public class JacksonJmxOperationResponseMapper implements JmxOperationResponseMa
|
||||
|
||||
public JacksonJmxOperationResponseMapper(ObjectMapper objectMapper) {
|
||||
this.objectMapper = (objectMapper != null) ? objectMapper : new ObjectMapper();
|
||||
this.listType = this.objectMapper.getTypeFactory()
|
||||
.constructParametricType(List.class, Object.class);
|
||||
this.mapType = this.objectMapper.getTypeFactory()
|
||||
.constructParametricType(Map.class, String.class, Object.class);
|
||||
this.listType = this.objectMapper.getTypeFactory().constructParametricType(List.class, Object.class);
|
||||
this.mapType = this.objectMapper.getTypeFactory().constructParametricType(Map.class, String.class,
|
||||
Object.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -43,8 +43,7 @@ import org.springframework.util.Assert;
|
||||
* @author Phillip Webb
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class JmxEndpointExporter
|
||||
implements InitializingBean, DisposableBean, BeanClassLoaderAware {
|
||||
public class JmxEndpointExporter implements InitializingBean, DisposableBean, BeanClassLoaderAware {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(JmxEndpointExporter.class);
|
||||
|
||||
@@ -60,10 +59,8 @@ public class JmxEndpointExporter
|
||||
|
||||
private Collection<ObjectName> registered;
|
||||
|
||||
public JmxEndpointExporter(MBeanServer mBeanServer,
|
||||
EndpointObjectNameFactory objectNameFactory,
|
||||
JmxOperationResponseMapper responseMapper,
|
||||
Collection<? extends ExposableJmxEndpoint> endpoints) {
|
||||
public JmxEndpointExporter(MBeanServer mBeanServer, EndpointObjectNameFactory objectNameFactory,
|
||||
JmxOperationResponseMapper responseMapper, Collection<? extends ExposableJmxEndpoint> endpoints) {
|
||||
Assert.notNull(mBeanServer, "MBeanServer must not be null");
|
||||
Assert.notNull(objectNameFactory, "ObjectNameFactory must not be null");
|
||||
Assert.notNull(responseMapper, "ResponseMapper must not be null");
|
||||
@@ -97,19 +94,15 @@ public class JmxEndpointExporter
|
||||
Assert.notNull(endpoint, "Endpoint must not be null");
|
||||
try {
|
||||
ObjectName name = this.objectNameFactory.getObjectName(endpoint);
|
||||
EndpointMBean mbean = new EndpointMBean(this.responseMapper, this.classLoader,
|
||||
endpoint);
|
||||
EndpointMBean mbean = new EndpointMBean(this.responseMapper, this.classLoader, endpoint);
|
||||
this.mBeanServer.registerMBean(mbean, name);
|
||||
return name;
|
||||
}
|
||||
catch (MalformedObjectNameException ex) {
|
||||
throw new IllegalStateException(
|
||||
"Invalid ObjectName for " + getEndpointDescription(endpoint), ex);
|
||||
throw new IllegalStateException("Invalid ObjectName for " + getEndpointDescription(endpoint), ex);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new MBeanExportException(
|
||||
"Failed to register MBean for " + getEndpointDescription(endpoint),
|
||||
ex);
|
||||
throw new MBeanExportException("Failed to register MBean for " + getEndpointDescription(endpoint), ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,8 +113,7 @@ public class JmxEndpointExporter
|
||||
private void unregister(ObjectName objectName) {
|
||||
try {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Unregister endpoint with ObjectName '" + objectName + "' "
|
||||
+ "from the JMX domain");
|
||||
logger.debug("Unregister endpoint with ObjectName '" + objectName + "' " + "from the JMX domain");
|
||||
}
|
||||
this.mBeanServer.unregisterMBean(objectName);
|
||||
}
|
||||
@@ -129,9 +121,7 @@ public class JmxEndpointExporter
|
||||
// Ignore and continue
|
||||
}
|
||||
catch (MBeanRegistrationException ex) {
|
||||
throw new JmxException(
|
||||
"Failed to unregister MBean with ObjectName '" + objectName + "'",
|
||||
ex);
|
||||
throw new JmxException("Failed to unregister MBean with ObjectName '" + objectName + "'", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -53,8 +53,8 @@ class MBeanInfoFactory {
|
||||
String className = EndpointMBean.class.getName();
|
||||
String description = getDescription(endpoint);
|
||||
ModelMBeanOperationInfo[] operations = getMBeanOperations(endpoint);
|
||||
return new ModelMBeanInfoSupport(className, description, NO_ATTRIBUTES,
|
||||
NO_CONSTRUCTORS, operations, NO_NOTIFICATIONS);
|
||||
return new ModelMBeanInfoSupport(className, description, NO_ATTRIBUTES, NO_CONSTRUCTORS, operations,
|
||||
NO_NOTIFICATIONS);
|
||||
}
|
||||
|
||||
private String getDescription(ExposableJmxEndpoint endpoint) {
|
||||
@@ -62,8 +62,7 @@ class MBeanInfoFactory {
|
||||
}
|
||||
|
||||
private ModelMBeanOperationInfo[] getMBeanOperations(ExposableJmxEndpoint endpoint) {
|
||||
return endpoint.getOperations().stream().map(this::getMBeanOperation)
|
||||
.toArray(ModelMBeanOperationInfo[]::new);
|
||||
return endpoint.getOperations().stream().map(this::getMBeanOperation).toArray(ModelMBeanOperationInfo[]::new);
|
||||
}
|
||||
|
||||
private ModelMBeanOperationInfo getMBeanOperation(JmxOperation operation) {
|
||||
@@ -76,21 +75,18 @@ class MBeanInfoFactory {
|
||||
}
|
||||
|
||||
private MBeanParameterInfo[] getSignature(List<JmxOperationParameter> parameters) {
|
||||
return parameters.stream().map(this::getMBeanParameter)
|
||||
.toArray(MBeanParameterInfo[]::new);
|
||||
return parameters.stream().map(this::getMBeanParameter).toArray(MBeanParameterInfo[]::new);
|
||||
}
|
||||
|
||||
private MBeanParameterInfo getMBeanParameter(JmxOperationParameter parameter) {
|
||||
return new MBeanParameterInfo(parameter.getName(), parameter.getType().getName(),
|
||||
parameter.getDescription());
|
||||
return new MBeanParameterInfo(parameter.getName(), parameter.getType().getName(), parameter.getDescription());
|
||||
}
|
||||
|
||||
private int getImpact(OperationType operationType) {
|
||||
if (operationType == OperationType.READ) {
|
||||
return MBeanOperationInfo.INFO;
|
||||
}
|
||||
if (operationType == OperationType.WRITE
|
||||
|| operationType == OperationType.DELETE) {
|
||||
if (operationType == OperationType.WRITE || operationType == OperationType.DELETE) {
|
||||
return MBeanOperationInfo.ACTION;
|
||||
}
|
||||
return MBeanOperationInfo.UNKNOWN;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -29,12 +29,10 @@ import org.springframework.boot.actuate.endpoint.jmx.JmxOperation;
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class DiscoveredJmxEndpoint extends AbstractDiscoveredEndpoint<JmxOperation>
|
||||
implements ExposableJmxEndpoint {
|
||||
class DiscoveredJmxEndpoint extends AbstractDiscoveredEndpoint<JmxOperation> implements ExposableJmxEndpoint {
|
||||
|
||||
DiscoveredJmxEndpoint(EndpointDiscoverer<?, ?> discoverer, Object endpointBean,
|
||||
EndpointId id, boolean enabledByDefault,
|
||||
Collection<JmxOperation> operations) {
|
||||
DiscoveredJmxEndpoint(EndpointDiscoverer<?, ?> discoverer, Object endpointBean, EndpointId id,
|
||||
boolean enabledByDefault, Collection<JmxOperation> operations) {
|
||||
super(discoverer, endpointBean, id, enabledByDefault, operations);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -60,14 +60,12 @@ class DiscoveredJmxOperation extends AbstractDiscoveredOperation implements JmxO
|
||||
|
||||
private final List<JmxOperationParameter> parameters;
|
||||
|
||||
DiscoveredJmxOperation(EndpointId endpointId,
|
||||
DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
|
||||
DiscoveredJmxOperation(EndpointId endpointId, DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
|
||||
super(operationMethod, invoker);
|
||||
Method method = operationMethod.getMethod();
|
||||
this.name = method.getName();
|
||||
this.outputType = JmxType.get(method.getReturnType());
|
||||
this.description = getDescription(method,
|
||||
() -> "Invoke " + this.name + " for endpoint " + endpointId);
|
||||
this.description = getDescription(method, () -> "Invoke " + this.name + " for endpoint " + endpointId);
|
||||
this.parameters = getParameters(operationMethod);
|
||||
}
|
||||
|
||||
@@ -84,29 +82,24 @@ class DiscoveredJmxOperation extends AbstractDiscoveredOperation implements JmxO
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Method method = operationMethod.getMethod();
|
||||
ManagedOperationParameter[] managed = jmxAttributeSource
|
||||
.getManagedOperationParameters(method);
|
||||
ManagedOperationParameter[] managed = jmxAttributeSource.getManagedOperationParameters(method);
|
||||
if (managed.length == 0) {
|
||||
return asList(operationMethod.getParameters().stream()
|
||||
.map(DiscoveredJmxOperationParameter::new));
|
||||
return asList(operationMethod.getParameters().stream().map(DiscoveredJmxOperationParameter::new));
|
||||
}
|
||||
return mergeParameters(operationMethod.getParameters(), managed);
|
||||
}
|
||||
|
||||
private List<JmxOperationParameter> mergeParameters(
|
||||
OperationParameters operationParameters,
|
||||
private List<JmxOperationParameter> mergeParameters(OperationParameters operationParameters,
|
||||
ManagedOperationParameter[] managedParameters) {
|
||||
List<JmxOperationParameter> merged = new ArrayList<>(managedParameters.length);
|
||||
for (int i = 0; i < managedParameters.length; i++) {
|
||||
merged.add(new DiscoveredJmxOperationParameter(managedParameters[i],
|
||||
operationParameters.get(i)));
|
||||
merged.add(new DiscoveredJmxOperationParameter(managedParameters[i], operationParameters.get(i)));
|
||||
}
|
||||
return Collections.unmodifiableList(merged);
|
||||
}
|
||||
|
||||
private <T> List<T> asList(Stream<T> stream) {
|
||||
return stream.collect(Collectors.collectingAndThen(Collectors.toList(),
|
||||
Collections::unmodifiableList));
|
||||
return stream.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -131,16 +124,14 @@ class DiscoveredJmxOperation extends AbstractDiscoveredOperation implements JmxO
|
||||
|
||||
@Override
|
||||
protected void appendFields(ToStringCreator creator) {
|
||||
creator.append("name", this.name).append("outputType", this.outputType)
|
||||
.append("description", this.description)
|
||||
creator.append("name", this.name).append("outputType", this.outputType).append("description", this.description)
|
||||
.append("parameters", this.parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* A discovered {@link JmxOperationParameter}.
|
||||
*/
|
||||
private static class DiscoveredJmxOperationParameter
|
||||
implements JmxOperationParameter {
|
||||
private static class DiscoveredJmxOperationParameter implements JmxOperationParameter {
|
||||
|
||||
private final String name;
|
||||
|
||||
@@ -197,8 +188,7 @@ class DiscoveredJmxOperation extends AbstractDiscoveredOperation implements JmxO
|
||||
if (source.isEnum()) {
|
||||
return String.class;
|
||||
}
|
||||
if (Date.class.isAssignableFrom(source)
|
||||
|| Instant.class.isAssignableFrom(source)) {
|
||||
if (Date.class.isAssignableFrom(source) || Instant.class.isAssignableFrom(source)) {
|
||||
return String.class;
|
||||
}
|
||||
if (source.getName().startsWith("java.")) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -36,8 +36,7 @@ import org.springframework.context.ApplicationContext;
|
||||
* @author Phillip Webb
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class JmxEndpointDiscoverer
|
||||
extends EndpointDiscoverer<ExposableJmxEndpoint, JmxOperation>
|
||||
public class JmxEndpointDiscoverer extends EndpointDiscoverer<ExposableJmxEndpoint, JmxOperation>
|
||||
implements JmxEndpointsSupplier {
|
||||
|
||||
/**
|
||||
@@ -47,30 +46,27 @@ public class JmxEndpointDiscoverer
|
||||
* @param invokerAdvisors invoker advisors to apply
|
||||
* @param filters filters to apply
|
||||
*/
|
||||
public JmxEndpointDiscoverer(ApplicationContext applicationContext,
|
||||
ParameterValueMapper parameterValueMapper,
|
||||
public JmxEndpointDiscoverer(ApplicationContext applicationContext, ParameterValueMapper parameterValueMapper,
|
||||
Collection<OperationInvokerAdvisor> invokerAdvisors,
|
||||
Collection<EndpointFilter<ExposableJmxEndpoint>> filters) {
|
||||
super(applicationContext, parameterValueMapper, invokerAdvisors, filters);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ExposableJmxEndpoint createEndpoint(Object endpointBean, EndpointId id,
|
||||
boolean enabledByDefault, Collection<JmxOperation> operations) {
|
||||
return new DiscoveredJmxEndpoint(this, endpointBean, id, enabledByDefault,
|
||||
operations);
|
||||
protected ExposableJmxEndpoint createEndpoint(Object endpointBean, EndpointId id, boolean enabledByDefault,
|
||||
Collection<JmxOperation> operations) {
|
||||
return new DiscoveredJmxEndpoint(this, endpointBean, id, enabledByDefault, operations);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JmxOperation createOperation(EndpointId endpointId,
|
||||
DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
|
||||
protected JmxOperation createOperation(EndpointId endpointId, DiscoveredOperationMethod operationMethod,
|
||||
OperationInvoker invoker) {
|
||||
return new DiscoveredJmxOperation(endpointId, operationMethod, invoker);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OperationKey createOperationKey(JmxOperation operation) {
|
||||
return new OperationKey(operation.getName(),
|
||||
() -> "MBean call '" + operation.getName() + "'");
|
||||
return new OperationKey(operation.getName(), () -> "MBean call '" + operation.getName() + "'");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -52,12 +52,10 @@ public class EndpointLinksResolver {
|
||||
* @param endpoints the endpoints
|
||||
* @param basePath the basePath
|
||||
*/
|
||||
public EndpointLinksResolver(Collection<? extends ExposableEndpoint<?>> endpoints,
|
||||
String basePath) {
|
||||
public EndpointLinksResolver(Collection<? extends ExposableEndpoint<?>> endpoints, String basePath) {
|
||||
this.endpoints = endpoints;
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Exposing " + endpoints.size()
|
||||
+ " endpoint(s) beneath base path '" + basePath + "'");
|
||||
logger.info("Exposing " + endpoints.size() + " endpoint(s) beneath base path '" + basePath + "'");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,8 +89,7 @@ public class EndpointLinksResolver {
|
||||
return requestUrl;
|
||||
}
|
||||
|
||||
private void collectLinks(Map<String, Link> links, ExposableWebEndpoint endpoint,
|
||||
String normalizedUrl) {
|
||||
private void collectLinks(Map<String, Link> links, ExposableWebEndpoint endpoint, String normalizedUrl) {
|
||||
for (WebOperation operation : endpoint.getOperations()) {
|
||||
links.put(operation.getId(), createLink(normalizedUrl, operation));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -61,11 +61,9 @@ public final class EndpointServlet {
|
||||
|
||||
public EndpointServlet withInitParameters(Map<String, String> initParameters) {
|
||||
Assert.notNull(initParameters, "InitParameters must not be null");
|
||||
boolean hasEmptyName = initParameters.keySet().stream()
|
||||
.anyMatch((name) -> !StringUtils.hasText(name));
|
||||
boolean hasEmptyName = initParameters.keySet().stream().anyMatch((name) -> !StringUtils.hasText(name));
|
||||
Assert.isTrue(!hasEmptyName, "InitParameters must not contain empty names");
|
||||
Map<String, String> mergedInitParameters = new LinkedHashMap<>(
|
||||
this.initParameters);
|
||||
Map<String, String> mergedInitParameters = new LinkedHashMap<>(this.initParameters);
|
||||
mergedInitParameters.putAll(initParameters);
|
||||
return new EndpointServlet(this.servlet, mergedInitParameters);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -25,8 +25,7 @@ import org.springframework.boot.actuate.endpoint.Operation;
|
||||
* @author Phillip Webb
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public interface ExposableServletEndpoint
|
||||
extends ExposableEndpoint<Operation>, PathMappedEndpoint {
|
||||
public interface ExposableServletEndpoint extends ExposableEndpoint<Operation>, PathMappedEndpoint {
|
||||
|
||||
/**
|
||||
* Return details of the servlet that should registered.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -24,7 +24,6 @@ import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
|
||||
* @author Phillip Webb
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public interface ExposableWebEndpoint
|
||||
extends ExposableEndpoint<WebOperation>, PathMappedEndpoint {
|
||||
public interface ExposableWebEndpoint extends ExposableEndpoint<WebOperation>, PathMappedEndpoint {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -56,21 +56,18 @@ public class PathMappedEndpoints implements Iterable<PathMappedEndpoint> {
|
||||
* @param basePath the base path of the endpoints
|
||||
* @param suppliers the endpoint suppliers
|
||||
*/
|
||||
public PathMappedEndpoints(String basePath,
|
||||
Collection<EndpointsSupplier<?>> suppliers) {
|
||||
public PathMappedEndpoints(String basePath, Collection<EndpointsSupplier<?>> suppliers) {
|
||||
Assert.notNull(suppliers, "Suppliers must not be null");
|
||||
this.basePath = (basePath != null) ? basePath : "";
|
||||
this.endpoints = getEndpoints(suppliers);
|
||||
}
|
||||
|
||||
private Map<EndpointId, PathMappedEndpoint> getEndpoints(
|
||||
Collection<EndpointsSupplier<?>> suppliers) {
|
||||
private Map<EndpointId, PathMappedEndpoint> getEndpoints(Collection<EndpointsSupplier<?>> suppliers) {
|
||||
Map<EndpointId, PathMappedEndpoint> endpoints = new LinkedHashMap<>();
|
||||
suppliers.forEach((supplier) -> {
|
||||
supplier.getEndpoints().forEach((endpoint) -> {
|
||||
if (endpoint instanceof PathMappedEndpoint) {
|
||||
endpoints.put(endpoint.getEndpointId(),
|
||||
(PathMappedEndpoint) endpoint);
|
||||
endpoints.put(endpoint.getEndpointId(), (PathMappedEndpoint) endpoint);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -150,8 +147,7 @@ public class PathMappedEndpoints implements Iterable<PathMappedEndpoint> {
|
||||
}
|
||||
|
||||
private <T> List<T> asList(Stream<T> stream) {
|
||||
return stream.collect(Collectors.collectingAndThen(Collectors.toList(),
|
||||
Collections::unmodifiableList));
|
||||
return stream.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -45,8 +45,7 @@ public class ServletEndpointRegistrar implements ServletContextInitializer {
|
||||
|
||||
private final Collection<ExposableServletEndpoint> servletEndpoints;
|
||||
|
||||
public ServletEndpointRegistrar(String basePath,
|
||||
Collection<ExposableServletEndpoint> servletEndpoints) {
|
||||
public ServletEndpointRegistrar(String basePath, Collection<ExposableServletEndpoint> servletEndpoints) {
|
||||
Assert.notNull(servletEndpoints, "ServletEndpoints must not be null");
|
||||
this.basePath = cleanBasePath(basePath);
|
||||
this.servletEndpoints = servletEndpoints;
|
||||
@@ -61,18 +60,15 @@ public class ServletEndpointRegistrar implements ServletContextInitializer {
|
||||
|
||||
@Override
|
||||
public void onStartup(ServletContext servletContext) throws ServletException {
|
||||
this.servletEndpoints
|
||||
.forEach((servletEndpoint) -> register(servletContext, servletEndpoint));
|
||||
this.servletEndpoints.forEach((servletEndpoint) -> register(servletContext, servletEndpoint));
|
||||
}
|
||||
|
||||
private void register(ServletContext servletContext,
|
||||
ExposableServletEndpoint endpoint) {
|
||||
private void register(ServletContext servletContext, ExposableServletEndpoint endpoint) {
|
||||
String name = endpoint.getEndpointId().toLowerCaseString() + "-actuator-endpoint";
|
||||
String path = this.basePath + "/" + endpoint.getRootPath();
|
||||
String urlMapping = path.endsWith("/") ? path + "*" : path + "/*";
|
||||
EndpointServlet endpointServlet = endpoint.getEndpointServlet();
|
||||
Dynamic registration = servletContext.addServlet(name,
|
||||
endpointServlet.getServlet());
|
||||
Dynamic registration = servletContext.addServlet(name, endpointServlet.getServlet());
|
||||
registration.addMapping(urlMapping);
|
||||
registration.setInitParameters(endpointServlet.getInitParameters());
|
||||
logger.info("Registered '" + path + "' to " + name);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -50,8 +50,8 @@ public final class WebOperationRequestPredicate {
|
||||
* @param produces the media types that the operation produces
|
||||
* @param consumes the media types that the operation consumes
|
||||
*/
|
||||
public WebOperationRequestPredicate(String path, WebEndpointHttpMethod httpMethod,
|
||||
Collection<String> consumes, Collection<String> produces) {
|
||||
public WebOperationRequestPredicate(String path, WebEndpointHttpMethod httpMethod, Collection<String> consumes,
|
||||
Collection<String> produces) {
|
||||
this.path = path;
|
||||
this.canonicalPath = PATH_VAR_PATTERN.matcher(path).replaceAll("{*}");
|
||||
this.httpMethod = httpMethod;
|
||||
@@ -121,15 +121,12 @@ public final class WebOperationRequestPredicate {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder result = new StringBuilder(
|
||||
this.httpMethod + " to path '" + this.path + "'");
|
||||
StringBuilder result = new StringBuilder(this.httpMethod + " to path '" + this.path + "'");
|
||||
if (!CollectionUtils.isEmpty(this.consumes)) {
|
||||
result.append(" consumes: "
|
||||
+ StringUtils.collectionToCommaDelimitedString(this.consumes));
|
||||
result.append(" consumes: " + StringUtils.collectionToCommaDelimitedString(this.consumes));
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(this.produces)) {
|
||||
result.append(" produces: "
|
||||
+ StringUtils.collectionToCommaDelimitedString(this.produces));
|
||||
result.append(" produces: " + StringUtils.collectionToCommaDelimitedString(this.produces));
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -39,8 +39,7 @@ import org.springframework.util.ClassUtils;
|
||||
* @author Phillip Webb
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class ControllerEndpointDiscoverer
|
||||
extends EndpointDiscoverer<ExposableControllerEndpoint, Operation>
|
||||
public class ControllerEndpointDiscoverer extends EndpointDiscoverer<ExposableControllerEndpoint, Operation>
|
||||
implements ControllerEndpointsSupplier {
|
||||
|
||||
private final List<PathMapper> endpointPathMappers;
|
||||
@@ -51,11 +50,9 @@ public class ControllerEndpointDiscoverer
|
||||
* @param endpointPathMappers the endpoint path mappers
|
||||
* @param filters filters to apply
|
||||
*/
|
||||
public ControllerEndpointDiscoverer(ApplicationContext applicationContext,
|
||||
List<PathMapper> endpointPathMappers,
|
||||
public ControllerEndpointDiscoverer(ApplicationContext applicationContext, List<PathMapper> endpointPathMappers,
|
||||
Collection<EndpointFilter<ExposableControllerEndpoint>> filters) {
|
||||
super(applicationContext, ParameterValueMapper.NONE, Collections.emptyList(),
|
||||
filters);
|
||||
super(applicationContext, ParameterValueMapper.NONE, Collections.emptyList(), filters);
|
||||
this.endpointPathMappers = endpointPathMappers;
|
||||
}
|
||||
|
||||
@@ -67,24 +64,21 @@ public class ControllerEndpointDiscoverer
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ExposableControllerEndpoint createEndpoint(Object endpointBean,
|
||||
EndpointId id, boolean enabledByDefault, Collection<Operation> operations) {
|
||||
protected ExposableControllerEndpoint createEndpoint(Object endpointBean, EndpointId id, boolean enabledByDefault,
|
||||
Collection<Operation> operations) {
|
||||
String rootPath = PathMapper.getRootPath(this.endpointPathMappers, id);
|
||||
return new DiscoveredControllerEndpoint(this, endpointBean, id, rootPath,
|
||||
enabledByDefault);
|
||||
return new DiscoveredControllerEndpoint(this, endpointBean, id, rootPath, enabledByDefault);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Operation createOperation(EndpointId endpointId,
|
||||
DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
|
||||
throw new IllegalStateException(
|
||||
"ControllerEndpoints must not declare operations");
|
||||
protected Operation createOperation(EndpointId endpointId, DiscoveredOperationMethod operationMethod,
|
||||
OperationInvoker invoker) {
|
||||
throw new IllegalStateException("ControllerEndpoints must not declare operations");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OperationKey createOperationKey(Operation operation) {
|
||||
throw new IllegalStateException(
|
||||
"ControllerEndpoints must not declare operations");
|
||||
throw new IllegalStateException("ControllerEndpoints must not declare operations");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -25,7 +25,6 @@ import org.springframework.boot.actuate.endpoint.EndpointsSupplier;
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ControllerEndpointsSupplier
|
||||
extends EndpointsSupplier<ExposableControllerEndpoint> {
|
||||
public interface ControllerEndpointsSupplier extends EndpointsSupplier<ExposableControllerEndpoint> {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -33,8 +33,8 @@ class DiscoveredControllerEndpoint extends AbstractDiscoveredEndpoint<Operation>
|
||||
|
||||
private final String rootPath;
|
||||
|
||||
DiscoveredControllerEndpoint(EndpointDiscoverer<?, ?> discoverer, Object endpointBean,
|
||||
EndpointId id, String rootPath, boolean enabledByDefault) {
|
||||
DiscoveredControllerEndpoint(EndpointDiscoverer<?, ?> discoverer, Object endpointBean, EndpointId id,
|
||||
String rootPath, boolean enabledByDefault) {
|
||||
super(discoverer, endpointBean, id, enabledByDefault, Collections.emptyList());
|
||||
this.rootPath = rootPath;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -32,24 +32,22 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class DiscoveredServletEndpoint extends AbstractDiscoveredEndpoint<Operation>
|
||||
implements ExposableServletEndpoint {
|
||||
class DiscoveredServletEndpoint extends AbstractDiscoveredEndpoint<Operation> implements ExposableServletEndpoint {
|
||||
|
||||
private final String rootPath;
|
||||
|
||||
private final EndpointServlet endpointServlet;
|
||||
|
||||
DiscoveredServletEndpoint(EndpointDiscoverer<?, ?> discoverer, Object endpointBean,
|
||||
EndpointId id, String rootPath, boolean enabledByDefault) {
|
||||
DiscoveredServletEndpoint(EndpointDiscoverer<?, ?> discoverer, Object endpointBean, EndpointId id, String rootPath,
|
||||
boolean enabledByDefault) {
|
||||
super(discoverer, endpointBean, id, enabledByDefault, Collections.emptyList());
|
||||
String beanType = endpointBean.getClass().getName();
|
||||
Assert.state(endpointBean instanceof Supplier,
|
||||
() -> "ServletEndpoint bean " + beanType + " must be a supplier");
|
||||
Object supplied = ((Supplier<?>) endpointBean).get();
|
||||
Assert.state(supplied != null,
|
||||
() -> "ServletEndpoint bean " + beanType + " must not supply null");
|
||||
Assert.state(supplied instanceof EndpointServlet, () -> "ServletEndpoint bean "
|
||||
+ beanType + " must supply an EndpointServlet");
|
||||
Assert.state(supplied != null, () -> "ServletEndpoint bean " + beanType + " must not supply null");
|
||||
Assert.state(supplied instanceof EndpointServlet,
|
||||
() -> "ServletEndpoint bean " + beanType + " must supply an EndpointServlet");
|
||||
this.endpointServlet = (EndpointServlet) supplied;
|
||||
this.rootPath = rootPath;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -29,14 +29,12 @@ import org.springframework.boot.actuate.endpoint.web.WebOperation;
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class DiscoveredWebEndpoint extends AbstractDiscoveredEndpoint<WebOperation>
|
||||
implements ExposableWebEndpoint {
|
||||
class DiscoveredWebEndpoint extends AbstractDiscoveredEndpoint<WebOperation> implements ExposableWebEndpoint {
|
||||
|
||||
private final String rootPath;
|
||||
|
||||
DiscoveredWebEndpoint(EndpointDiscoverer<?, ?> discoverer, Object endpointBean,
|
||||
EndpointId id, String rootPath, boolean enabledByDefault,
|
||||
Collection<WebOperation> operations) {
|
||||
DiscoveredWebEndpoint(EndpointDiscoverer<?, ?> discoverer, Object endpointBean, EndpointId id, String rootPath,
|
||||
boolean enabledByDefault, Collection<WebOperation> operations) {
|
||||
super(discoverer, endpointBean, id, enabledByDefault, operations);
|
||||
this.rootPath = rootPath;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -42,8 +42,7 @@ import org.springframework.util.ClassUtils;
|
||||
*/
|
||||
class DiscoveredWebOperation extends AbstractDiscoveredOperation implements WebOperation {
|
||||
|
||||
private static final boolean REACTIVE_STREAMS_PRESENT = ClassUtils.isPresent(
|
||||
"org.reactivestreams.Publisher",
|
||||
private static final boolean REACTIVE_STREAMS_PRESENT = ClassUtils.isPresent("org.reactivestreams.Publisher",
|
||||
DiscoveredWebOperation.class.getClassLoader());
|
||||
|
||||
private final String id;
|
||||
@@ -52,8 +51,7 @@ class DiscoveredWebOperation extends AbstractDiscoveredOperation implements WebO
|
||||
|
||||
private final WebOperationRequestPredicate requestPredicate;
|
||||
|
||||
DiscoveredWebOperation(EndpointId endpointId,
|
||||
DiscoveredOperationMethod operationMethod, OperationInvoker invoker,
|
||||
DiscoveredWebOperation(EndpointId endpointId, DiscoveredOperationMethod operationMethod, OperationInvoker invoker,
|
||||
WebOperationRequestPredicate requestPredicate) {
|
||||
super(operationMethod, invoker);
|
||||
Method method = operationMethod.getMethod();
|
||||
@@ -63,8 +61,8 @@ class DiscoveredWebOperation extends AbstractDiscoveredOperation implements WebO
|
||||
}
|
||||
|
||||
private String getId(EndpointId endpointId, Method method) {
|
||||
return endpointId + Stream.of(method.getParameters()).filter(this::hasSelector)
|
||||
.map(this::dashName).collect(Collectors.joining());
|
||||
return endpointId + Stream.of(method.getParameters()).filter(this::hasSelector).map(this::dashName)
|
||||
.collect(Collectors.joining());
|
||||
}
|
||||
|
||||
private boolean hasSelector(Parameter parameter) {
|
||||
@@ -76,8 +74,7 @@ class DiscoveredWebOperation extends AbstractDiscoveredOperation implements WebO
|
||||
}
|
||||
|
||||
private boolean getBlocking(Method method) {
|
||||
return !REACTIVE_STREAMS_PRESENT
|
||||
|| !Publisher.class.isAssignableFrom(method.getReturnType());
|
||||
return !REACTIVE_STREAMS_PRESENT || !Publisher.class.isAssignableFrom(method.getReturnType());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -97,8 +94,8 @@ class DiscoveredWebOperation extends AbstractDiscoveredOperation implements WebO
|
||||
|
||||
@Override
|
||||
protected void appendFields(ToStringCreator creator) {
|
||||
creator.append("id", this.id).append("blocking", this.blocking)
|
||||
.append("requestPredicate", this.requestPredicate);
|
||||
creator.append("id", this.id).append("blocking", this.blocking).append("requestPredicate",
|
||||
this.requestPredicate);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -29,8 +29,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
* @author Phillip Webb
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public interface ExposableControllerEndpoint
|
||||
extends ExposableEndpoint<Operation>, PathMappedEndpoint {
|
||||
public interface ExposableControllerEndpoint extends ExposableEndpoint<Operation>, PathMappedEndpoint {
|
||||
|
||||
/**
|
||||
* Return the source controller that contains {@link RequestMapping} methods.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -51,20 +51,19 @@ class RequestPredicateFactory {
|
||||
this.endpointMediaTypes = endpointMediaTypes;
|
||||
}
|
||||
|
||||
public WebOperationRequestPredicate getRequestPredicate(EndpointId endpointId,
|
||||
String rootPath, DiscoveredOperationMethod operationMethod) {
|
||||
public WebOperationRequestPredicate getRequestPredicate(EndpointId endpointId, String rootPath,
|
||||
DiscoveredOperationMethod operationMethod) {
|
||||
Method method = operationMethod.getMethod();
|
||||
String path = getPath(rootPath, method);
|
||||
WebEndpointHttpMethod httpMethod = determineHttpMethod(
|
||||
operationMethod.getOperationType());
|
||||
WebEndpointHttpMethod httpMethod = determineHttpMethod(operationMethod.getOperationType());
|
||||
Collection<String> consumes = getConsumes(httpMethod, method);
|
||||
Collection<String> produces = getProduces(operationMethod, method);
|
||||
return new WebOperationRequestPredicate(path, httpMethod, consumes, produces);
|
||||
}
|
||||
|
||||
private String getPath(String rootPath, Method method) {
|
||||
return rootPath + Stream.of(method.getParameters()).filter(this::hasSelector)
|
||||
.map(this::slashName).collect(Collectors.joining());
|
||||
return rootPath + Stream.of(method.getParameters()).filter(this::hasSelector).map(this::slashName)
|
||||
.collect(Collectors.joining());
|
||||
}
|
||||
|
||||
private boolean hasSelector(Parameter parameter) {
|
||||
@@ -75,21 +74,18 @@ class RequestPredicateFactory {
|
||||
return "/{" + parameter.getName() + "}";
|
||||
}
|
||||
|
||||
private Collection<String> getConsumes(WebEndpointHttpMethod httpMethod,
|
||||
Method method) {
|
||||
private Collection<String> getConsumes(WebEndpointHttpMethod httpMethod, Method method) {
|
||||
if (WebEndpointHttpMethod.POST == httpMethod && consumesRequestBody(method)) {
|
||||
return this.endpointMediaTypes.getConsumed();
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private Collection<String> getProduces(DiscoveredOperationMethod operationMethod,
|
||||
Method method) {
|
||||
private Collection<String> getProduces(DiscoveredOperationMethod operationMethod, Method method) {
|
||||
if (!operationMethod.getProducesMediaTypes().isEmpty()) {
|
||||
return operationMethod.getProducesMediaTypes();
|
||||
}
|
||||
if (Void.class.equals(method.getReturnType())
|
||||
|| void.class.equals(method.getReturnType())) {
|
||||
if (Void.class.equals(method.getReturnType()) || void.class.equals(method.getReturnType())) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
if (producesResource(method)) {
|
||||
@@ -104,8 +100,7 @@ class RequestPredicateFactory {
|
||||
}
|
||||
if (WebEndpointResponse.class.isAssignableFrom(method.getReturnType())) {
|
||||
ResolvableType returnType = ResolvableType.forMethodReturnType(method);
|
||||
if (ResolvableType.forClass(Resource.class)
|
||||
.isAssignableFrom(returnType.getGeneric(0))) {
|
||||
if (ResolvableType.forClass(Resource.class).isAssignableFrom(returnType.getGeneric(0))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -39,8 +39,7 @@ import org.springframework.util.ClassUtils;
|
||||
* @author Phillip Webb
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class ServletEndpointDiscoverer
|
||||
extends EndpointDiscoverer<ExposableServletEndpoint, Operation>
|
||||
public class ServletEndpointDiscoverer extends EndpointDiscoverer<ExposableServletEndpoint, Operation>
|
||||
implements ServletEndpointsSupplier {
|
||||
|
||||
private final List<PathMapper> endpointPathMappers;
|
||||
@@ -51,11 +50,9 @@ public class ServletEndpointDiscoverer
|
||||
* @param endpointPathMappers the endpoint path mappers
|
||||
* @param filters filters to apply
|
||||
*/
|
||||
public ServletEndpointDiscoverer(ApplicationContext applicationContext,
|
||||
List<PathMapper> endpointPathMappers,
|
||||
public ServletEndpointDiscoverer(ApplicationContext applicationContext, List<PathMapper> endpointPathMappers,
|
||||
Collection<EndpointFilter<ExposableServletEndpoint>> filters) {
|
||||
super(applicationContext, ParameterValueMapper.NONE, Collections.emptyList(),
|
||||
filters);
|
||||
super(applicationContext, ParameterValueMapper.NONE, Collections.emptyList(), filters);
|
||||
this.endpointPathMappers = endpointPathMappers;
|
||||
}
|
||||
|
||||
@@ -66,16 +63,15 @@ public class ServletEndpointDiscoverer
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ExposableServletEndpoint createEndpoint(Object endpointBean, EndpointId id,
|
||||
boolean enabledByDefault, Collection<Operation> operations) {
|
||||
protected ExposableServletEndpoint createEndpoint(Object endpointBean, EndpointId id, boolean enabledByDefault,
|
||||
Collection<Operation> operations) {
|
||||
String rootPath = PathMapper.getRootPath(this.endpointPathMappers, id);
|
||||
return new DiscoveredServletEndpoint(this, endpointBean, id, rootPath,
|
||||
enabledByDefault);
|
||||
return new DiscoveredServletEndpoint(this, endpointBean, id, rootPath, enabledByDefault);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Operation createOperation(EndpointId endpointId,
|
||||
DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
|
||||
protected Operation createOperation(EndpointId endpointId, DiscoveredOperationMethod operationMethod,
|
||||
OperationInvoker invoker) {
|
||||
throw new IllegalStateException("ServletEndpoints must not declare operations");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -26,7 +26,6 @@ import org.springframework.boot.actuate.endpoint.web.ExposableServletEndpoint;
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ServletEndpointsSupplier
|
||||
extends EndpointsSupplier<ExposableServletEndpoint> {
|
||||
public interface ServletEndpointsSupplier extends EndpointsSupplier<ExposableServletEndpoint> {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -40,8 +40,7 @@ import org.springframework.context.ApplicationContext;
|
||||
* @author Phillip Webb
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class WebEndpointDiscoverer
|
||||
extends EndpointDiscoverer<ExposableWebEndpoint, WebOperation>
|
||||
public class WebEndpointDiscoverer extends EndpointDiscoverer<ExposableWebEndpoint, WebOperation>
|
||||
implements WebEndpointsSupplier {
|
||||
|
||||
private final List<PathMapper> endpointPathMappers;
|
||||
@@ -57,8 +56,7 @@ public class WebEndpointDiscoverer
|
||||
* @param invokerAdvisors invoker advisors to apply
|
||||
* @param filters filters to apply
|
||||
*/
|
||||
public WebEndpointDiscoverer(ApplicationContext applicationContext,
|
||||
ParameterValueMapper parameterValueMapper,
|
||||
public WebEndpointDiscoverer(ApplicationContext applicationContext, ParameterValueMapper parameterValueMapper,
|
||||
EndpointMediaTypes endpointMediaTypes, List<PathMapper> endpointPathMappers,
|
||||
Collection<OperationInvokerAdvisor> invokerAdvisors,
|
||||
Collection<EndpointFilter<ExposableWebEndpoint>> filters) {
|
||||
@@ -68,21 +66,19 @@ public class WebEndpointDiscoverer
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ExposableWebEndpoint createEndpoint(Object endpointBean, EndpointId id,
|
||||
boolean enabledByDefault, Collection<WebOperation> operations) {
|
||||
protected ExposableWebEndpoint createEndpoint(Object endpointBean, EndpointId id, boolean enabledByDefault,
|
||||
Collection<WebOperation> operations) {
|
||||
String rootPath = PathMapper.getRootPath(this.endpointPathMappers, id);
|
||||
return new DiscoveredWebEndpoint(this, endpointBean, id, rootPath,
|
||||
enabledByDefault, operations);
|
||||
return new DiscoveredWebEndpoint(this, endpointBean, id, rootPath, enabledByDefault, operations);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WebOperation createOperation(EndpointId endpointId,
|
||||
DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
|
||||
protected WebOperation createOperation(EndpointId endpointId, DiscoveredOperationMethod operationMethod,
|
||||
OperationInvoker invoker) {
|
||||
String rootPath = PathMapper.getRootPath(this.endpointPathMappers, endpointId);
|
||||
WebOperationRequestPredicate requestPredicate = this.requestPredicateFactory
|
||||
.getRequestPredicate(endpointId, rootPath, operationMethod);
|
||||
return new DiscoveredWebOperation(endpointId, operationMethod, invoker,
|
||||
requestPredicate);
|
||||
WebOperationRequestPredicate requestPredicate = this.requestPredicateFactory.getRequestPredicate(endpointId,
|
||||
rootPath, operationMethod);
|
||||
return new DiscoveredWebOperation(endpointId, operationMethod, invoker, requestPredicate);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -74,38 +74,33 @@ public class JerseyEndpointResourceFactory {
|
||||
* @return the resources for the operations
|
||||
*/
|
||||
public Collection<Resource> createEndpointResources(EndpointMapping endpointMapping,
|
||||
Collection<ExposableWebEndpoint> endpoints,
|
||||
EndpointMediaTypes endpointMediaTypes, EndpointLinksResolver linksResolver) {
|
||||
Collection<ExposableWebEndpoint> endpoints, EndpointMediaTypes endpointMediaTypes,
|
||||
EndpointLinksResolver linksResolver) {
|
||||
List<Resource> resources = new ArrayList<>();
|
||||
endpoints.stream().flatMap((endpoint) -> endpoint.getOperations().stream())
|
||||
.map((operation) -> createResource(endpointMapping, operation))
|
||||
.forEach(resources::add);
|
||||
.map((operation) -> createResource(endpointMapping, operation)).forEach(resources::add);
|
||||
if (StringUtils.hasText(endpointMapping.getPath())) {
|
||||
Resource resource = createEndpointLinksResource(endpointMapping.getPath(),
|
||||
endpointMediaTypes, linksResolver);
|
||||
Resource resource = createEndpointLinksResource(endpointMapping.getPath(), endpointMediaTypes,
|
||||
linksResolver);
|
||||
resources.add(resource);
|
||||
}
|
||||
return resources;
|
||||
}
|
||||
|
||||
private Resource createResource(EndpointMapping endpointMapping,
|
||||
WebOperation operation) {
|
||||
private Resource createResource(EndpointMapping endpointMapping, WebOperation operation) {
|
||||
WebOperationRequestPredicate requestPredicate = operation.getRequestPredicate();
|
||||
Builder resourceBuilder = Resource.builder()
|
||||
.path(endpointMapping.createSubPath(requestPredicate.getPath()));
|
||||
Builder resourceBuilder = Resource.builder().path(endpointMapping.createSubPath(requestPredicate.getPath()));
|
||||
resourceBuilder.addMethod(requestPredicate.getHttpMethod().name())
|
||||
.consumes(StringUtils.toStringArray(requestPredicate.getConsumes()))
|
||||
.produces(StringUtils.toStringArray(requestPredicate.getProduces()))
|
||||
.handledBy(new OperationInflector(operation,
|
||||
!requestPredicate.getConsumes().isEmpty()));
|
||||
.handledBy(new OperationInflector(operation, !requestPredicate.getConsumes().isEmpty()));
|
||||
return resourceBuilder.build();
|
||||
}
|
||||
|
||||
private Resource createEndpointLinksResource(String endpointPath,
|
||||
EndpointMediaTypes endpointMediaTypes, EndpointLinksResolver linksResolver) {
|
||||
private Resource createEndpointLinksResource(String endpointPath, EndpointMediaTypes endpointMediaTypes,
|
||||
EndpointLinksResolver linksResolver) {
|
||||
Builder resourceBuilder = Resource.builder().path(endpointPath);
|
||||
resourceBuilder.addMethod("GET")
|
||||
.produces(StringUtils.toStringArray(endpointMediaTypes.getProduced()))
|
||||
resourceBuilder.addMethod("GET").produces(StringUtils.toStringArray(endpointMediaTypes.getProduced()))
|
||||
.handledBy(new EndpointLinksInflector(linksResolver));
|
||||
return resourceBuilder.build();
|
||||
}
|
||||
@@ -113,16 +108,14 @@ public class JerseyEndpointResourceFactory {
|
||||
/**
|
||||
* {@link Inflector} to invoke the {@link WebOperation}.
|
||||
*/
|
||||
private static final class OperationInflector
|
||||
implements Inflector<ContainerRequestContext, Object> {
|
||||
private static final class OperationInflector implements Inflector<ContainerRequestContext, Object> {
|
||||
|
||||
private static final List<Function<Object, Object>> BODY_CONVERTERS;
|
||||
|
||||
static {
|
||||
List<Function<Object, Object>> converters = new ArrayList<>();
|
||||
converters.add(new ResourceBodyConverter());
|
||||
if (ClassUtils.isPresent("reactor.core.publisher.Mono",
|
||||
OperationInflector.class.getClassLoader())) {
|
||||
if (ClassUtils.isPresent("reactor.core.publisher.Mono", OperationInflector.class.getClassLoader())) {
|
||||
converters.add(new MonoBodyConverter());
|
||||
}
|
||||
BODY_CONVERTERS = Collections.unmodifiableList(converters);
|
||||
@@ -146,8 +139,8 @@ public class JerseyEndpointResourceFactory {
|
||||
arguments.putAll(extractPathParameters(data));
|
||||
arguments.putAll(extractQueryParameters(data));
|
||||
try {
|
||||
Object response = this.operation.invoke(new InvocationContext(
|
||||
new JerseySecurityContext(data.getSecurityContext()), arguments));
|
||||
Object response = this.operation
|
||||
.invoke(new InvocationContext(new JerseySecurityContext(data.getSecurityContext()), arguments));
|
||||
return convertToJaxRsResponse(response, data.getRequest().getMethod());
|
||||
}
|
||||
catch (InvalidEndpointRequestException ex) {
|
||||
@@ -164,18 +157,15 @@ public class JerseyEndpointResourceFactory {
|
||||
return (Map<String, Object>) entity;
|
||||
}
|
||||
|
||||
private Map<String, Object> extractPathParameters(
|
||||
ContainerRequestContext requestContext) {
|
||||
private Map<String, Object> extractPathParameters(ContainerRequestContext requestContext) {
|
||||
return extract(requestContext.getUriInfo().getPathParameters());
|
||||
}
|
||||
|
||||
private Map<String, Object> extractQueryParameters(
|
||||
ContainerRequestContext requestContext) {
|
||||
private Map<String, Object> extractQueryParameters(ContainerRequestContext requestContext) {
|
||||
return extract(requestContext.getUriInfo().getQueryParameters());
|
||||
}
|
||||
|
||||
private Map<String, Object> extract(
|
||||
MultivaluedMap<String, String> multivaluedMap) {
|
||||
private Map<String, Object> extract(MultivaluedMap<String, String> multivaluedMap) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
multivaluedMap.forEach((name, values) -> {
|
||||
if (!CollectionUtils.isEmpty(values)) {
|
||||
@@ -193,13 +183,11 @@ public class JerseyEndpointResourceFactory {
|
||||
}
|
||||
try {
|
||||
if (!(response instanceof WebEndpointResponse)) {
|
||||
return Response.status(Status.OK).entity(convertIfNecessary(response))
|
||||
.build();
|
||||
return Response.status(Status.OK).entity(convertIfNecessary(response)).build();
|
||||
}
|
||||
WebEndpointResponse<?> webEndpointResponse = (WebEndpointResponse<?>) response;
|
||||
return Response.status(webEndpointResponse.getStatus())
|
||||
.entity(convertIfNecessary(webEndpointResponse.getBody()))
|
||||
.build();
|
||||
.entity(convertIfNecessary(webEndpointResponse.getBody())).build();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
return Response.status(Status.INTERNAL_SERVER_ERROR).build();
|
||||
@@ -254,8 +242,7 @@ public class JerseyEndpointResourceFactory {
|
||||
/**
|
||||
* {@link Inflector} to for endpoint links.
|
||||
*/
|
||||
private static final class EndpointLinksInflector
|
||||
implements Inflector<ContainerRequestContext, Response> {
|
||||
private static final class EndpointLinksInflector implements Inflector<ContainerRequestContext, Response> {
|
||||
|
||||
private final EndpointLinksResolver linksResolver;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -77,8 +77,7 @@ import org.springframework.web.util.pattern.PathPatternParser;
|
||||
* @author Brian Clozel
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public abstract class AbstractWebFluxEndpointHandlerMapping
|
||||
extends RequestMappingInfoHandlerMapping {
|
||||
public abstract class AbstractWebFluxEndpointHandlerMapping extends RequestMappingInfoHandlerMapping {
|
||||
|
||||
private static final PathPatternParser pathPatternParser = new PathPatternParser();
|
||||
|
||||
@@ -90,11 +89,11 @@ public abstract class AbstractWebFluxEndpointHandlerMapping
|
||||
|
||||
private final CorsConfiguration corsConfiguration;
|
||||
|
||||
private final Method handleWriteMethod = ReflectionUtils.findMethod(
|
||||
WriteOperationHandler.class, "handle", ServerWebExchange.class, Map.class);
|
||||
private final Method handleWriteMethod = ReflectionUtils.findMethod(WriteOperationHandler.class, "handle",
|
||||
ServerWebExchange.class, Map.class);
|
||||
|
||||
private final Method handleReadMethod = ReflectionUtils
|
||||
.findMethod(ReadOperationHandler.class, "handle", ServerWebExchange.class);
|
||||
private final Method handleReadMethod = ReflectionUtils.findMethod(ReadOperationHandler.class, "handle",
|
||||
ServerWebExchange.class);
|
||||
|
||||
/**
|
||||
* Creates a new {@code AbstractWebFluxEndpointHandlerMapping} that provides mappings
|
||||
@@ -105,8 +104,8 @@ public abstract class AbstractWebFluxEndpointHandlerMapping
|
||||
* @param corsConfiguration the CORS configuration for the endpoints
|
||||
*/
|
||||
public AbstractWebFluxEndpointHandlerMapping(EndpointMapping endpointMapping,
|
||||
Collection<ExposableWebEndpoint> endpoints,
|
||||
EndpointMediaTypes endpointMediaTypes, CorsConfiguration corsConfiguration) {
|
||||
Collection<ExposableWebEndpoint> endpoints, EndpointMediaTypes endpointMediaTypes,
|
||||
CorsConfiguration corsConfiguration) {
|
||||
this.endpointMapping = endpointMapping;
|
||||
this.endpoints = endpoints;
|
||||
this.endpointMediaTypes = endpointMediaTypes;
|
||||
@@ -129,22 +128,18 @@ public abstract class AbstractWebFluxEndpointHandlerMapping
|
||||
@Override
|
||||
protected HandlerMethod createHandlerMethod(Object handler, Method method) {
|
||||
HandlerMethod handlerMethod = super.createHandlerMethod(handler, method);
|
||||
return new WebFluxEndpointHandlerMethod(handlerMethod.getBean(),
|
||||
handlerMethod.getMethod());
|
||||
return new WebFluxEndpointHandlerMethod(handlerMethod.getBean(), handlerMethod.getMethod());
|
||||
}
|
||||
|
||||
private void registerMappingForOperation(ExposableWebEndpoint endpoint,
|
||||
WebOperation operation) {
|
||||
ReactiveWebOperation reactiveWebOperation = wrapReactiveWebOperation(endpoint,
|
||||
operation, new ReactiveWebOperationAdapter(operation));
|
||||
private void registerMappingForOperation(ExposableWebEndpoint endpoint, WebOperation operation) {
|
||||
ReactiveWebOperation reactiveWebOperation = wrapReactiveWebOperation(endpoint, operation,
|
||||
new ReactiveWebOperationAdapter(operation));
|
||||
if (operation.getType() == OperationType.WRITE) {
|
||||
registerMapping(createRequestMappingInfo(operation),
|
||||
new WriteOperationHandler((reactiveWebOperation)),
|
||||
registerMapping(createRequestMappingInfo(operation), new WriteOperationHandler((reactiveWebOperation)),
|
||||
this.handleWriteMethod);
|
||||
}
|
||||
else {
|
||||
registerMapping(createRequestMappingInfo(operation),
|
||||
new ReadOperationHandler((reactiveWebOperation)),
|
||||
registerMapping(createRequestMappingInfo(operation), new ReadOperationHandler((reactiveWebOperation)),
|
||||
this.handleReadMethod);
|
||||
}
|
||||
}
|
||||
@@ -157,42 +152,38 @@ public abstract class AbstractWebFluxEndpointHandlerMapping
|
||||
* @param reactiveWebOperation the reactive web operation to wrap
|
||||
* @return a wrapped reactive web operation
|
||||
*/
|
||||
protected ReactiveWebOperation wrapReactiveWebOperation(ExposableWebEndpoint endpoint,
|
||||
WebOperation operation, ReactiveWebOperation reactiveWebOperation) {
|
||||
protected ReactiveWebOperation wrapReactiveWebOperation(ExposableWebEndpoint endpoint, WebOperation operation,
|
||||
ReactiveWebOperation reactiveWebOperation) {
|
||||
return reactiveWebOperation;
|
||||
}
|
||||
|
||||
private RequestMappingInfo createRequestMappingInfo(WebOperation operation) {
|
||||
WebOperationRequestPredicate predicate = operation.getRequestPredicate();
|
||||
PatternsRequestCondition patterns = new PatternsRequestCondition(pathPatternParser
|
||||
.parse(this.endpointMapping.createSubPath(predicate.getPath())));
|
||||
PatternsRequestCondition patterns = new PatternsRequestCondition(
|
||||
pathPatternParser.parse(this.endpointMapping.createSubPath(predicate.getPath())));
|
||||
RequestMethodsRequestCondition methods = new RequestMethodsRequestCondition(
|
||||
RequestMethod.valueOf(predicate.getHttpMethod().name()));
|
||||
ConsumesRequestCondition consumes = new ConsumesRequestCondition(
|
||||
StringUtils.toStringArray(predicate.getConsumes()));
|
||||
ProducesRequestCondition produces = new ProducesRequestCondition(
|
||||
StringUtils.toStringArray(predicate.getProduces()));
|
||||
return new RequestMappingInfo(null, patterns, methods, null, null, consumes,
|
||||
produces, null);
|
||||
return new RequestMappingInfo(null, patterns, methods, null, null, consumes, produces, null);
|
||||
}
|
||||
|
||||
private void registerLinksMapping() {
|
||||
PatternsRequestCondition patterns = new PatternsRequestCondition(
|
||||
pathPatternParser.parse(this.endpointMapping.getPath()));
|
||||
RequestMethodsRequestCondition methods = new RequestMethodsRequestCondition(
|
||||
RequestMethod.GET);
|
||||
RequestMethodsRequestCondition methods = new RequestMethodsRequestCondition(RequestMethod.GET);
|
||||
ProducesRequestCondition produces = new ProducesRequestCondition(
|
||||
StringUtils.toStringArray(this.endpointMediaTypes.getProduced()));
|
||||
RequestMappingInfo mapping = new RequestMappingInfo(patterns, methods, null, null,
|
||||
null, produces, null);
|
||||
RequestMappingInfo mapping = new RequestMappingInfo(patterns, methods, null, null, null, produces, null);
|
||||
LinksHandler linksHandler = getLinksHandler();
|
||||
registerMapping(mapping, linksHandler, ReflectionUtils
|
||||
.findMethod(linksHandler.getClass(), "links", ServerWebExchange.class));
|
||||
registerMapping(mapping, linksHandler,
|
||||
ReflectionUtils.findMethod(linksHandler.getClass(), "links", ServerWebExchange.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CorsConfiguration initCorsConfiguration(Object handler, Method method,
|
||||
RequestMappingInfo mapping) {
|
||||
protected CorsConfiguration initCorsConfiguration(Object handler, Method method, RequestMappingInfo mapping) {
|
||||
return this.corsConfiguration;
|
||||
}
|
||||
|
||||
@@ -202,8 +193,7 @@ public abstract class AbstractWebFluxEndpointHandlerMapping
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RequestMappingInfo getMappingForMethod(Method method,
|
||||
Class<?> handlerType) {
|
||||
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -235,8 +225,7 @@ public abstract class AbstractWebFluxEndpointHandlerMapping
|
||||
|
||||
@Override
|
||||
public Object invoke(InvocationContext context) {
|
||||
return Mono.create(
|
||||
(sink) -> Schedulers.elastic().schedule(() -> invoke(context, sink)));
|
||||
return Mono.create((sink) -> Schedulers.elastic().schedule(() -> invoke(context, sink)));
|
||||
}
|
||||
|
||||
private void invoke(InvocationContext context, MonoSink<Object> sink) {
|
||||
@@ -267,8 +256,7 @@ public abstract class AbstractWebFluxEndpointHandlerMapping
|
||||
@FunctionalInterface
|
||||
protected interface ReactiveWebOperation {
|
||||
|
||||
Mono<ResponseEntity<Object>> handle(ServerWebExchange exchange,
|
||||
Map<String, String> body);
|
||||
Mono<ResponseEntity<Object>> handle(ServerWebExchange exchange, Map<String, String> body);
|
||||
|
||||
}
|
||||
|
||||
@@ -276,8 +264,7 @@ public abstract class AbstractWebFluxEndpointHandlerMapping
|
||||
* Adapter class to convert an {@link OperationInvoker} into a
|
||||
* {@link ReactiveWebOperation}.
|
||||
*/
|
||||
private static final class ReactiveWebOperationAdapter
|
||||
implements ReactiveWebOperation {
|
||||
private static final class ReactiveWebOperationAdapter implements ReactiveWebOperation {
|
||||
|
||||
private final OperationInvoker invoker;
|
||||
|
||||
@@ -300,8 +287,7 @@ public abstract class AbstractWebFluxEndpointHandlerMapping
|
||||
}
|
||||
|
||||
private Supplier<Mono<? extends SecurityContext>> getSecurityContextSupplier() {
|
||||
if (ClassUtils.isPresent(
|
||||
"org.springframework.security.core.context.ReactiveSecurityContextHolder",
|
||||
if (ClassUtils.isPresent("org.springframework.security.core.context.ReactiveSecurityContextHolder",
|
||||
getClass().getClassLoader())) {
|
||||
return this::springSecurityContext;
|
||||
}
|
||||
@@ -310,8 +296,7 @@ public abstract class AbstractWebFluxEndpointHandlerMapping
|
||||
|
||||
public Mono<? extends SecurityContext> springSecurityContext() {
|
||||
return ReactiveSecurityContextHolder.getContext()
|
||||
.map((securityContext) -> new ReactiveSecurityContext(
|
||||
securityContext.getAuthentication()))
|
||||
.map((securityContext) -> new ReactiveSecurityContext(securityContext.getAuthentication()))
|
||||
.switchIfEmpty(Mono.just(new ReactiveSecurityContext(null)));
|
||||
}
|
||||
|
||||
@@ -320,26 +305,22 @@ public abstract class AbstractWebFluxEndpointHandlerMapping
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<ResponseEntity<Object>> handle(ServerWebExchange exchange,
|
||||
Map<String, String> body) {
|
||||
public Mono<ResponseEntity<Object>> handle(ServerWebExchange exchange, Map<String, String> body) {
|
||||
Map<String, Object> arguments = getArguments(exchange, body);
|
||||
return this.securityContextSupplier.get()
|
||||
.map((securityContext) -> new InvocationContext(securityContext,
|
||||
arguments))
|
||||
.flatMap((invocationContext) -> handleResult(
|
||||
(Publisher<?>) this.invoker.invoke(invocationContext),
|
||||
.map((securityContext) -> new InvocationContext(securityContext, arguments))
|
||||
.flatMap((invocationContext) -> handleResult((Publisher<?>) this.invoker.invoke(invocationContext),
|
||||
exchange.getRequest().getMethod()));
|
||||
}
|
||||
|
||||
private Map<String, Object> getArguments(ServerWebExchange exchange,
|
||||
Map<String, String> body) {
|
||||
private Map<String, Object> getArguments(ServerWebExchange exchange, Map<String, String> body) {
|
||||
Map<String, Object> arguments = new LinkedHashMap<>();
|
||||
arguments.putAll(getTemplateVariables(exchange));
|
||||
if (body != null) {
|
||||
arguments.putAll(body);
|
||||
}
|
||||
exchange.getRequest().getQueryParams().forEach((name, values) -> arguments
|
||||
.put(name, (values.size() != 1) ? values : values.get(0)));
|
||||
exchange.getRequest().getQueryParams()
|
||||
.forEach((name, values) -> arguments.put(name, (values.size() != 1) ? values : values.get(0)));
|
||||
return arguments;
|
||||
}
|
||||
|
||||
@@ -347,14 +328,12 @@ public abstract class AbstractWebFluxEndpointHandlerMapping
|
||||
return exchange.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||
}
|
||||
|
||||
private Mono<ResponseEntity<Object>> handleResult(Publisher<?> result,
|
||||
HttpMethod httpMethod) {
|
||||
private Mono<ResponseEntity<Object>> handleResult(Publisher<?> result, HttpMethod httpMethod) {
|
||||
return Mono.from(result).map(this::toResponseEntity)
|
||||
.onErrorMap(InvalidEndpointRequestException.class,
|
||||
(ex) -> new ResponseStatusException(HttpStatus.BAD_REQUEST,
|
||||
ex.getReason()))
|
||||
.defaultIfEmpty(new ResponseEntity<>((httpMethod != HttpMethod.GET)
|
||||
? HttpStatus.NO_CONTENT : HttpStatus.NOT_FOUND));
|
||||
(ex) -> new ResponseStatusException(HttpStatus.BAD_REQUEST, ex.getReason()))
|
||||
.defaultIfEmpty(new ResponseEntity<>(
|
||||
(httpMethod != HttpMethod.GET) ? HttpStatus.NO_CONTENT : HttpStatus.NOT_FOUND));
|
||||
}
|
||||
|
||||
private ResponseEntity<Object> toResponseEntity(Object response) {
|
||||
@@ -424,8 +403,7 @@ public abstract class AbstractWebFluxEndpointHandlerMapping
|
||||
@Override
|
||||
public HandlerMethod createWithResolvedBean() {
|
||||
HandlerMethod handlerMethod = super.createWithResolvedBean();
|
||||
return new WebFluxEndpointHandlerMethod(handlerMethod.getBean(),
|
||||
handlerMethod.getMethod());
|
||||
return new WebFluxEndpointHandlerMethod(handlerMethod.getBean(), handlerMethod.getMethod());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -451,8 +429,7 @@ public abstract class AbstractWebFluxEndpointHandlerMapping
|
||||
role = this.roleVoter.getRolePrefix() + role;
|
||||
}
|
||||
return this.roleVoter.vote(this.authentication, null,
|
||||
Collections.singletonList(new SecurityConfig(
|
||||
role))) == AccessDecisionVoter.ACCESS_GRANTED;
|
||||
Collections.singletonList(new SecurityConfig(role))) == AccessDecisionVoter.ACCESS_GRANTED;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -59,8 +59,7 @@ public class ControllerEndpointHandlerMapping extends RequestMappingHandlerMappi
|
||||
* @param corsConfiguration the CORS configuration for the endpoints or {@code null}
|
||||
*/
|
||||
public ControllerEndpointHandlerMapping(EndpointMapping endpointMapping,
|
||||
Collection<ExposableControllerEndpoint> endpoints,
|
||||
CorsConfiguration corsConfiguration) {
|
||||
Collection<ExposableControllerEndpoint> endpoints, CorsConfiguration corsConfiguration) {
|
||||
Assert.notNull(endpointMapping, "EndpointMapping must not be null");
|
||||
Assert.notNull(endpoints, "Endpoints must not be null");
|
||||
this.endpointMapping = endpointMapping;
|
||||
@@ -69,8 +68,7 @@ public class ControllerEndpointHandlerMapping extends RequestMappingHandlerMappi
|
||||
setOrder(-100);
|
||||
}
|
||||
|
||||
private Map<Object, ExposableControllerEndpoint> getHandlers(
|
||||
Collection<ExposableControllerEndpoint> endpoints) {
|
||||
private Map<Object, ExposableControllerEndpoint> getHandlers(Collection<ExposableControllerEndpoint> endpoints) {
|
||||
Map<Object, ExposableControllerEndpoint> handlers = new LinkedHashMap<>();
|
||||
endpoints.forEach((endpoint) -> handlers.put(endpoint.getController(), endpoint));
|
||||
return Collections.unmodifiableMap(handlers);
|
||||
@@ -82,44 +80,36 @@ public class ControllerEndpointHandlerMapping extends RequestMappingHandlerMappi
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerHandlerMethod(Object handler, Method method,
|
||||
RequestMappingInfo mapping) {
|
||||
protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
|
||||
ExposableControllerEndpoint endpoint = this.handlers.get(handler);
|
||||
mapping = withEndpointMappedPatterns(endpoint, mapping);
|
||||
super.registerHandlerMethod(handler, method, mapping);
|
||||
}
|
||||
|
||||
private RequestMappingInfo withEndpointMappedPatterns(
|
||||
ExposableControllerEndpoint endpoint, RequestMappingInfo mapping) {
|
||||
private RequestMappingInfo withEndpointMappedPatterns(ExposableControllerEndpoint endpoint,
|
||||
RequestMappingInfo mapping) {
|
||||
Set<PathPattern> patterns = mapping.getPatternsCondition().getPatterns();
|
||||
if (patterns.isEmpty()) {
|
||||
patterns = Collections.singleton(getPathPatternParser().parse(""));
|
||||
}
|
||||
PathPattern[] endpointMappedPatterns = patterns.stream()
|
||||
.map((pattern) -> getEndpointMappedPattern(endpoint, pattern))
|
||||
.toArray(PathPattern[]::new);
|
||||
.map((pattern) -> getEndpointMappedPattern(endpoint, pattern)).toArray(PathPattern[]::new);
|
||||
return withNewPatterns(mapping, endpointMappedPatterns);
|
||||
}
|
||||
|
||||
private PathPattern getEndpointMappedPattern(ExposableControllerEndpoint endpoint,
|
||||
PathPattern pattern) {
|
||||
return getPathPatternParser().parse(
|
||||
this.endpointMapping.createSubPath(endpoint.getRootPath() + pattern));
|
||||
private PathPattern getEndpointMappedPattern(ExposableControllerEndpoint endpoint, PathPattern pattern) {
|
||||
return getPathPatternParser().parse(this.endpointMapping.createSubPath(endpoint.getRootPath() + pattern));
|
||||
}
|
||||
|
||||
private RequestMappingInfo withNewPatterns(RequestMappingInfo mapping,
|
||||
PathPattern[] patterns) {
|
||||
PatternsRequestCondition patternsCondition = new PatternsRequestCondition(
|
||||
patterns);
|
||||
return new RequestMappingInfo(patternsCondition, mapping.getMethodsCondition(),
|
||||
mapping.getParamsCondition(), mapping.getHeadersCondition(),
|
||||
mapping.getConsumesCondition(), mapping.getProducesCondition(),
|
||||
private RequestMappingInfo withNewPatterns(RequestMappingInfo mapping, PathPattern[] patterns) {
|
||||
PatternsRequestCondition patternsCondition = new PatternsRequestCondition(patterns);
|
||||
return new RequestMappingInfo(patternsCondition, mapping.getMethodsCondition(), mapping.getParamsCondition(),
|
||||
mapping.getHeadersCondition(), mapping.getConsumesCondition(), mapping.getProducesCondition(),
|
||||
mapping.getCustomCondition());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CorsConfiguration initCorsConfiguration(Object handler, Method method,
|
||||
RequestMappingInfo mapping) {
|
||||
protected CorsConfiguration initCorsConfiguration(Object handler, Method method, RequestMappingInfo mapping) {
|
||||
return this.corsConfiguration;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -41,8 +41,7 @@ import org.springframework.web.util.UriComponentsBuilder;
|
||||
* @author Brian Clozel
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class WebFluxEndpointHandlerMapping extends AbstractWebFluxEndpointHandlerMapping
|
||||
implements InitializingBean {
|
||||
public class WebFluxEndpointHandlerMapping extends AbstractWebFluxEndpointHandlerMapping implements InitializingBean {
|
||||
|
||||
private final EndpointLinksResolver linksResolver;
|
||||
|
||||
@@ -55,8 +54,7 @@ public class WebFluxEndpointHandlerMapping extends AbstractWebFluxEndpointHandle
|
||||
* @param corsConfiguration the CORS configuration for the endpoints or {@code null}
|
||||
* @param linksResolver resolver for determining links to available endpoints
|
||||
*/
|
||||
public WebFluxEndpointHandlerMapping(EndpointMapping endpointMapping,
|
||||
Collection<ExposableWebEndpoint> endpoints,
|
||||
public WebFluxEndpointHandlerMapping(EndpointMapping endpointMapping, Collection<ExposableWebEndpoint> endpoints,
|
||||
EndpointMediaTypes endpointMediaTypes, CorsConfiguration corsConfiguration,
|
||||
EndpointLinksResolver linksResolver) {
|
||||
super(endpointMapping, endpoints, endpointMediaTypes, corsConfiguration);
|
||||
@@ -77,12 +75,10 @@ public class WebFluxEndpointHandlerMapping extends AbstractWebFluxEndpointHandle
|
||||
@Override
|
||||
@ResponseBody
|
||||
public Map<String, Map<String, Link>> links(ServerWebExchange exchange) {
|
||||
String requestUri = UriComponentsBuilder
|
||||
.fromUri(exchange.getRequest().getURI()).replaceQuery(null)
|
||||
String requestUri = UriComponentsBuilder.fromUri(exchange.getRequest().getURI()).replaceQuery(null)
|
||||
.toUriString();
|
||||
return Collections.singletonMap("_links",
|
||||
WebFluxEndpointHandlerMapping.this.linksResolver
|
||||
.resolveLinks(requestUri));
|
||||
WebFluxEndpointHandlerMapping.this.linksResolver.resolveLinks(requestUri));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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,8 +70,7 @@ import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMappi
|
||||
* @author Brian Clozel
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public abstract class AbstractWebMvcEndpointHandlerMapping
|
||||
extends RequestMappingInfoHandlerMapping
|
||||
public abstract class AbstractWebMvcEndpointHandlerMapping extends RequestMappingInfoHandlerMapping
|
||||
implements InitializingBean, MatchableHandlerMapping {
|
||||
|
||||
private final EndpointMapping endpointMapping;
|
||||
@@ -82,8 +81,8 @@ public abstract class AbstractWebMvcEndpointHandlerMapping
|
||||
|
||||
private final CorsConfiguration corsConfiguration;
|
||||
|
||||
private final Method handleMethod = ReflectionUtils.findMethod(OperationHandler.class,
|
||||
"handle", HttpServletRequest.class, Map.class);
|
||||
private final Method handleMethod = ReflectionUtils.findMethod(OperationHandler.class, "handle",
|
||||
HttpServletRequest.class, Map.class);
|
||||
|
||||
private static final RequestMappingInfo.BuilderConfiguration builderConfig = getBuilderConfig();
|
||||
|
||||
@@ -95,8 +94,7 @@ public abstract class AbstractWebMvcEndpointHandlerMapping
|
||||
* @param endpointMediaTypes media types consumed and produced by the endpoints
|
||||
*/
|
||||
public AbstractWebMvcEndpointHandlerMapping(EndpointMapping endpointMapping,
|
||||
Collection<ExposableWebEndpoint> endpoints,
|
||||
EndpointMediaTypes endpointMediaTypes) {
|
||||
Collection<ExposableWebEndpoint> endpoints, EndpointMediaTypes endpointMediaTypes) {
|
||||
this(endpointMapping, endpoints, endpointMediaTypes, null);
|
||||
}
|
||||
|
||||
@@ -109,8 +107,8 @@ public abstract class AbstractWebMvcEndpointHandlerMapping
|
||||
* @param corsConfiguration the CORS configuration for the endpoints or {@code null}
|
||||
*/
|
||||
public AbstractWebMvcEndpointHandlerMapping(EndpointMapping endpointMapping,
|
||||
Collection<ExposableWebEndpoint> endpoints,
|
||||
EndpointMediaTypes endpointMediaTypes, CorsConfiguration corsConfiguration) {
|
||||
Collection<ExposableWebEndpoint> endpoints, EndpointMediaTypes endpointMediaTypes,
|
||||
CorsConfiguration corsConfiguration) {
|
||||
this.endpointMapping = endpointMapping;
|
||||
this.endpoints = endpoints;
|
||||
this.endpointMediaTypes = endpointMediaTypes;
|
||||
@@ -133,22 +131,19 @@ public abstract class AbstractWebMvcEndpointHandlerMapping
|
||||
@Override
|
||||
protected HandlerMethod createHandlerMethod(Object handler, Method method) {
|
||||
HandlerMethod handlerMethod = super.createHandlerMethod(handler, method);
|
||||
return new WebMvcEndpointHandlerMethod(handlerMethod.getBean(),
|
||||
handlerMethod.getMethod());
|
||||
return new WebMvcEndpointHandlerMethod(handlerMethod.getBean(), handlerMethod.getMethod());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestMatchResult match(HttpServletRequest request, String pattern) {
|
||||
RequestMappingInfo info = RequestMappingInfo.paths(pattern).options(builderConfig)
|
||||
.build();
|
||||
RequestMappingInfo info = RequestMappingInfo.paths(pattern).options(builderConfig).build();
|
||||
RequestMappingInfo matchingInfo = info.getMatchingCondition(request);
|
||||
if (matchingInfo == null) {
|
||||
return null;
|
||||
}
|
||||
Set<String> patterns = matchingInfo.getPatternsCondition().getPatterns();
|
||||
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
|
||||
return new RequestMatchResult(patterns.iterator().next(), lookupPath,
|
||||
getPathMatcher());
|
||||
return new RequestMatchResult(patterns.iterator().next(), lookupPath, getPathMatcher());
|
||||
}
|
||||
|
||||
private static RequestMappingInfo.BuilderConfiguration getBuilderConfig() {
|
||||
@@ -160,12 +155,11 @@ public abstract class AbstractWebMvcEndpointHandlerMapping
|
||||
return config;
|
||||
}
|
||||
|
||||
private void registerMappingForOperation(ExposableWebEndpoint endpoint,
|
||||
WebOperation operation) {
|
||||
ServletWebOperation servletWebOperation = wrapServletWebOperation(endpoint,
|
||||
operation, new ServletWebOperationAdapter(operation));
|
||||
registerMapping(createRequestMappingInfo(operation),
|
||||
new OperationHandler(servletWebOperation), this.handleMethod);
|
||||
private void registerMappingForOperation(ExposableWebEndpoint endpoint, WebOperation operation) {
|
||||
ServletWebOperation servletWebOperation = wrapServletWebOperation(endpoint, operation,
|
||||
new ServletWebOperationAdapter(operation));
|
||||
registerMapping(createRequestMappingInfo(operation), new OperationHandler(servletWebOperation),
|
||||
this.handleMethod);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,50 +170,42 @@ public abstract class AbstractWebMvcEndpointHandlerMapping
|
||||
* @param servletWebOperation the servlet web operation to wrap
|
||||
* @return a wrapped servlet web operation
|
||||
*/
|
||||
protected ServletWebOperation wrapServletWebOperation(ExposableWebEndpoint endpoint,
|
||||
WebOperation operation, ServletWebOperation servletWebOperation) {
|
||||
protected ServletWebOperation wrapServletWebOperation(ExposableWebEndpoint endpoint, WebOperation operation,
|
||||
ServletWebOperation servletWebOperation) {
|
||||
return servletWebOperation;
|
||||
}
|
||||
|
||||
private RequestMappingInfo createRequestMappingInfo(WebOperation operation) {
|
||||
WebOperationRequestPredicate predicate = operation.getRequestPredicate();
|
||||
PatternsRequestCondition patterns = patternsRequestConditionForPattern(
|
||||
predicate.getPath());
|
||||
PatternsRequestCondition patterns = patternsRequestConditionForPattern(predicate.getPath());
|
||||
RequestMethodsRequestCondition methods = new RequestMethodsRequestCondition(
|
||||
RequestMethod.valueOf(predicate.getHttpMethod().name()));
|
||||
ConsumesRequestCondition consumes = new ConsumesRequestCondition(
|
||||
StringUtils.toStringArray(predicate.getConsumes()));
|
||||
ProducesRequestCondition produces = new ProducesRequestCondition(
|
||||
StringUtils.toStringArray(predicate.getProduces()));
|
||||
return new RequestMappingInfo(null, patterns, methods, null, null, consumes,
|
||||
produces, null);
|
||||
return new RequestMappingInfo(null, patterns, methods, null, null, consumes, produces, null);
|
||||
}
|
||||
|
||||
private void registerLinksMapping() {
|
||||
PatternsRequestCondition patterns = patternsRequestConditionForPattern("");
|
||||
RequestMethodsRequestCondition methods = new RequestMethodsRequestCondition(
|
||||
RequestMethod.GET);
|
||||
ProducesRequestCondition produces = new ProducesRequestCondition(
|
||||
this.endpointMediaTypes.getProduced().toArray(StringUtils
|
||||
.toStringArray(this.endpointMediaTypes.getProduced())));
|
||||
RequestMappingInfo mapping = new RequestMappingInfo(patterns, methods, null, null,
|
||||
null, produces, null);
|
||||
RequestMethodsRequestCondition methods = new RequestMethodsRequestCondition(RequestMethod.GET);
|
||||
ProducesRequestCondition produces = new ProducesRequestCondition(this.endpointMediaTypes.getProduced()
|
||||
.toArray(StringUtils.toStringArray(this.endpointMediaTypes.getProduced())));
|
||||
RequestMappingInfo mapping = new RequestMappingInfo(patterns, methods, null, null, null, produces, null);
|
||||
LinksHandler linksHandler = getLinksHandler();
|
||||
registerMapping(mapping, linksHandler,
|
||||
ReflectionUtils.findMethod(linksHandler.getClass(), "links",
|
||||
HttpServletRequest.class, HttpServletResponse.class));
|
||||
registerMapping(mapping, linksHandler, ReflectionUtils.findMethod(linksHandler.getClass(), "links",
|
||||
HttpServletRequest.class, HttpServletResponse.class));
|
||||
}
|
||||
|
||||
private PatternsRequestCondition patternsRequestConditionForPattern(String path) {
|
||||
String[] patterns = new String[] { this.endpointMapping.createSubPath(path) };
|
||||
return new PatternsRequestCondition(patterns, builderConfig.getUrlPathHelper(),
|
||||
builderConfig.getPathMatcher(), builderConfig.useSuffixPatternMatch(),
|
||||
builderConfig.useTrailingSlashMatch());
|
||||
return new PatternsRequestCondition(patterns, builderConfig.getUrlPathHelper(), builderConfig.getPathMatcher(),
|
||||
builderConfig.useSuffixPatternMatch(), builderConfig.useTrailingSlashMatch());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CorsConfiguration initCorsConfiguration(Object handler, Method method,
|
||||
RequestMappingInfo mapping) {
|
||||
protected CorsConfiguration initCorsConfiguration(Object handler, Method method, RequestMappingInfo mapping) {
|
||||
return this.corsConfiguration;
|
||||
}
|
||||
|
||||
@@ -229,8 +215,7 @@ public abstract class AbstractWebMvcEndpointHandlerMapping
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RequestMappingInfo getMappingForMethod(Method method,
|
||||
Class<?> handlerType) {
|
||||
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -286,13 +271,11 @@ public abstract class AbstractWebMvcEndpointHandlerMapping
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle(HttpServletRequest request,
|
||||
@RequestBody(required = false) Map<String, String> body) {
|
||||
public Object handle(HttpServletRequest request, @RequestBody(required = false) Map<String, String> body) {
|
||||
Map<String, Object> arguments = getArguments(request, body);
|
||||
try {
|
||||
return handleResult(
|
||||
this.operation.invoke(new InvocationContext(
|
||||
new ServletSecurityContext(request), arguments)),
|
||||
this.operation.invoke(new InvocationContext(new ServletSecurityContext(request), arguments)),
|
||||
HttpMethod.valueOf(request.getMethod()));
|
||||
}
|
||||
catch (InvalidEndpointRequestException ex) {
|
||||
@@ -305,35 +288,32 @@ public abstract class AbstractWebMvcEndpointHandlerMapping
|
||||
return "Actuator web endpoint '" + this.operation.getId() + "'";
|
||||
}
|
||||
|
||||
private Map<String, Object> getArguments(HttpServletRequest request,
|
||||
Map<String, String> body) {
|
||||
private Map<String, Object> getArguments(HttpServletRequest request, Map<String, String> body) {
|
||||
Map<String, Object> arguments = new LinkedHashMap<>();
|
||||
arguments.putAll(getTemplateVariables(request));
|
||||
if (body != null && HttpMethod.POST.name().equals(request.getMethod())) {
|
||||
arguments.putAll(body);
|
||||
}
|
||||
request.getParameterMap().forEach((name, values) -> arguments.put(name,
|
||||
(values.length != 1) ? Arrays.asList(values) : values[0]));
|
||||
request.getParameterMap().forEach(
|
||||
(name, values) -> arguments.put(name, (values.length != 1) ? Arrays.asList(values) : values[0]));
|
||||
return arguments;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, String> getTemplateVariables(HttpServletRequest request) {
|
||||
return (Map<String, String>) request
|
||||
.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||
return (Map<String, String>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||
}
|
||||
|
||||
private Object handleResult(Object result, HttpMethod httpMethod) {
|
||||
if (result == null) {
|
||||
return new ResponseEntity<>((httpMethod != HttpMethod.GET)
|
||||
? HttpStatus.NO_CONTENT : HttpStatus.NOT_FOUND);
|
||||
return new ResponseEntity<>(
|
||||
(httpMethod != HttpMethod.GET) ? HttpStatus.NO_CONTENT : HttpStatus.NOT_FOUND);
|
||||
}
|
||||
if (!(result instanceof WebEndpointResponse)) {
|
||||
return result;
|
||||
}
|
||||
WebEndpointResponse<?> response = (WebEndpointResponse<?>) result;
|
||||
return new ResponseEntity<Object>(response.getBody(),
|
||||
HttpStatus.valueOf(response.getStatus()));
|
||||
return new ResponseEntity<Object>(response.getBody(), HttpStatus.valueOf(response.getStatus()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -350,8 +330,7 @@ public abstract class AbstractWebMvcEndpointHandlerMapping
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
public Object handle(HttpServletRequest request,
|
||||
@RequestBody(required = false) Map<String, String> body) {
|
||||
public Object handle(HttpServletRequest request, @RequestBody(required = false) Map<String, String> body) {
|
||||
return this.operation.handle(request, body);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -59,8 +59,7 @@ public class ControllerEndpointHandlerMapping extends RequestMappingHandlerMappi
|
||||
* @param corsConfiguration the CORS configuration for the endpoints or {@code null}
|
||||
*/
|
||||
public ControllerEndpointHandlerMapping(EndpointMapping endpointMapping,
|
||||
Collection<ExposableControllerEndpoint> endpoints,
|
||||
CorsConfiguration corsConfiguration) {
|
||||
Collection<ExposableControllerEndpoint> endpoints, CorsConfiguration corsConfiguration) {
|
||||
Assert.notNull(endpointMapping, "EndpointMapping must not be null");
|
||||
Assert.notNull(endpoints, "Endpoints must not be null");
|
||||
this.endpointMapping = endpointMapping;
|
||||
@@ -70,8 +69,7 @@ public class ControllerEndpointHandlerMapping extends RequestMappingHandlerMappi
|
||||
setUseSuffixPatternMatch(false);
|
||||
}
|
||||
|
||||
private Map<Object, ExposableControllerEndpoint> getHandlers(
|
||||
Collection<ExposableControllerEndpoint> endpoints) {
|
||||
private Map<Object, ExposableControllerEndpoint> getHandlers(Collection<ExposableControllerEndpoint> endpoints) {
|
||||
Map<Object, ExposableControllerEndpoint> handlers = new LinkedHashMap<>();
|
||||
endpoints.forEach((endpoint) -> handlers.put(endpoint.getController(), endpoint));
|
||||
return Collections.unmodifiableMap(handlers);
|
||||
@@ -83,44 +81,37 @@ public class ControllerEndpointHandlerMapping extends RequestMappingHandlerMappi
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerHandlerMethod(Object handler, Method method,
|
||||
RequestMappingInfo mapping) {
|
||||
protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
|
||||
ExposableControllerEndpoint endpoint = this.handlers.get(handler);
|
||||
mapping = withEndpointMappedPatterns(endpoint, mapping);
|
||||
super.registerHandlerMethod(handler, method, mapping);
|
||||
}
|
||||
|
||||
private RequestMappingInfo withEndpointMappedPatterns(
|
||||
ExposableControllerEndpoint endpoint, RequestMappingInfo mapping) {
|
||||
private RequestMappingInfo withEndpointMappedPatterns(ExposableControllerEndpoint endpoint,
|
||||
RequestMappingInfo mapping) {
|
||||
Set<String> patterns = mapping.getPatternsCondition().getPatterns();
|
||||
if (patterns.isEmpty()) {
|
||||
patterns = Collections.singleton("");
|
||||
}
|
||||
String[] endpointMappedPatterns = patterns.stream()
|
||||
.map((pattern) -> getEndpointMappedPattern(endpoint, pattern))
|
||||
.toArray(String[]::new);
|
||||
.map((pattern) -> getEndpointMappedPattern(endpoint, pattern)).toArray(String[]::new);
|
||||
return withNewPatterns(mapping, endpointMappedPatterns);
|
||||
}
|
||||
|
||||
private String getEndpointMappedPattern(ExposableControllerEndpoint endpoint,
|
||||
String pattern) {
|
||||
private String getEndpointMappedPattern(ExposableControllerEndpoint endpoint, String pattern) {
|
||||
return this.endpointMapping.createSubPath(endpoint.getRootPath() + pattern);
|
||||
}
|
||||
|
||||
private RequestMappingInfo withNewPatterns(RequestMappingInfo mapping,
|
||||
String[] patterns) {
|
||||
PatternsRequestCondition patternsCondition = new PatternsRequestCondition(
|
||||
patterns, null, null, useSuffixPatternMatch(), useTrailingSlashMatch(),
|
||||
null);
|
||||
return new RequestMappingInfo(patternsCondition, mapping.getMethodsCondition(),
|
||||
mapping.getParamsCondition(), mapping.getHeadersCondition(),
|
||||
mapping.getConsumesCondition(), mapping.getProducesCondition(),
|
||||
private RequestMappingInfo withNewPatterns(RequestMappingInfo mapping, String[] patterns) {
|
||||
PatternsRequestCondition patternsCondition = new PatternsRequestCondition(patterns, null, null,
|
||||
useSuffixPatternMatch(), useTrailingSlashMatch(), null);
|
||||
return new RequestMappingInfo(patternsCondition, mapping.getMethodsCondition(), mapping.getParamsCondition(),
|
||||
mapping.getHeadersCondition(), mapping.getConsumesCondition(), mapping.getProducesCondition(),
|
||||
mapping.getCustomCondition());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CorsConfiguration initCorsConfiguration(Object handler, Method method,
|
||||
RequestMappingInfo mapping) {
|
||||
protected CorsConfiguration initCorsConfiguration(Object handler, Method method, RequestMappingInfo mapping) {
|
||||
return this.corsConfiguration;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -30,12 +30,11 @@ import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
*/
|
||||
final class SkipPathExtensionContentNegotiation extends HandlerInterceptorAdapter {
|
||||
|
||||
private static final String SKIP_ATTRIBUTE = PathExtensionContentNegotiationStrategy.class
|
||||
.getName() + ".SKIP";
|
||||
private static final String SKIP_ATTRIBUTE = PathExtensionContentNegotiationStrategy.class.getName() + ".SKIP";
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
|
||||
Object handler) throws Exception {
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
|
||||
throws Exception {
|
||||
request.setAttribute(SKIP_ATTRIBUTE, Boolean.TRUE);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -53,8 +53,7 @@ public class WebMvcEndpointHandlerMapping extends AbstractWebMvcEndpointHandlerM
|
||||
* @param corsConfiguration the CORS configuration for the endpoints or {@code null}
|
||||
* @param linksResolver resolver for determining links to available endpoints
|
||||
*/
|
||||
public WebMvcEndpointHandlerMapping(EndpointMapping endpointMapping,
|
||||
Collection<ExposableWebEndpoint> endpoints,
|
||||
public WebMvcEndpointHandlerMapping(EndpointMapping endpointMapping, Collection<ExposableWebEndpoint> endpoints,
|
||||
EndpointMediaTypes endpointMediaTypes, CorsConfiguration corsConfiguration,
|
||||
EndpointLinksResolver linksResolver) {
|
||||
super(endpointMapping, endpoints, endpointMediaTypes, corsConfiguration);
|
||||
@@ -74,11 +73,9 @@ public class WebMvcEndpointHandlerMapping extends AbstractWebMvcEndpointHandlerM
|
||||
|
||||
@Override
|
||||
@ResponseBody
|
||||
public Map<String, Map<String, Link>> links(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
public Map<String, Map<String, Link>> links(HttpServletRequest request, HttpServletResponse response) {
|
||||
return Collections.singletonMap("_links",
|
||||
WebMvcEndpointHandlerMapping.this.linksResolver
|
||||
.resolveLinks(request.getRequestURL().toString()));
|
||||
WebMvcEndpointHandlerMapping.this.linksResolver.resolveLinks(request.getRequestURL().toString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -86,66 +86,54 @@ public class EnvironmentEndpoint {
|
||||
return getEnvironmentEntryDescriptor(toMatch);
|
||||
}
|
||||
|
||||
private EnvironmentDescriptor getEnvironmentDescriptor(
|
||||
Predicate<String> propertyNamePredicate) {
|
||||
private EnvironmentDescriptor getEnvironmentDescriptor(Predicate<String> propertyNamePredicate) {
|
||||
PlaceholdersResolver resolver = getResolver();
|
||||
List<PropertySourceDescriptor> propertySources = new ArrayList<>();
|
||||
getPropertySourcesAsMap().forEach((sourceName, source) -> {
|
||||
if (source instanceof EnumerablePropertySource) {
|
||||
propertySources.add(
|
||||
describeSource(sourceName, (EnumerablePropertySource<?>) source,
|
||||
resolver, propertyNamePredicate));
|
||||
propertySources.add(describeSource(sourceName, (EnumerablePropertySource<?>) source, resolver,
|
||||
propertyNamePredicate));
|
||||
}
|
||||
});
|
||||
return new EnvironmentDescriptor(
|
||||
Arrays.asList(this.environment.getActiveProfiles()), propertySources);
|
||||
return new EnvironmentDescriptor(Arrays.asList(this.environment.getActiveProfiles()), propertySources);
|
||||
}
|
||||
|
||||
private EnvironmentEntryDescriptor getEnvironmentEntryDescriptor(
|
||||
String propertyName) {
|
||||
Map<String, PropertyValueDescriptor> descriptors = getPropertySourceDescriptors(
|
||||
propertyName);
|
||||
private EnvironmentEntryDescriptor getEnvironmentEntryDescriptor(String propertyName) {
|
||||
Map<String, PropertyValueDescriptor> descriptors = getPropertySourceDescriptors(propertyName);
|
||||
PropertySummaryDescriptor summary = getPropertySummaryDescriptor(descriptors);
|
||||
return new EnvironmentEntryDescriptor(summary,
|
||||
Arrays.asList(this.environment.getActiveProfiles()),
|
||||
return new EnvironmentEntryDescriptor(summary, Arrays.asList(this.environment.getActiveProfiles()),
|
||||
toPropertySourceDescriptors(descriptors));
|
||||
}
|
||||
|
||||
private List<PropertySourceEntryDescriptor> toPropertySourceDescriptors(
|
||||
Map<String, PropertyValueDescriptor> descriptors) {
|
||||
List<PropertySourceEntryDescriptor> result = new ArrayList<>();
|
||||
descriptors.forEach((name, property) -> result
|
||||
.add(new PropertySourceEntryDescriptor(name, property)));
|
||||
descriptors.forEach((name, property) -> result.add(new PropertySourceEntryDescriptor(name, property)));
|
||||
return result;
|
||||
}
|
||||
|
||||
private PropertySummaryDescriptor getPropertySummaryDescriptor(
|
||||
Map<String, PropertyValueDescriptor> descriptors) {
|
||||
private PropertySummaryDescriptor getPropertySummaryDescriptor(Map<String, PropertyValueDescriptor> descriptors) {
|
||||
for (Map.Entry<String, PropertyValueDescriptor> entry : descriptors.entrySet()) {
|
||||
if (entry.getValue() != null) {
|
||||
return new PropertySummaryDescriptor(entry.getKey(),
|
||||
entry.getValue().getValue());
|
||||
return new PropertySummaryDescriptor(entry.getKey(), entry.getValue().getValue());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Map<String, PropertyValueDescriptor> getPropertySourceDescriptors(
|
||||
String propertyName) {
|
||||
private Map<String, PropertyValueDescriptor> getPropertySourceDescriptors(String propertyName) {
|
||||
Map<String, PropertyValueDescriptor> propertySources = new LinkedHashMap<>();
|
||||
PlaceholdersResolver resolver = getResolver();
|
||||
getPropertySourcesAsMap().forEach((sourceName, source) -> propertySources
|
||||
.put(sourceName, source.containsProperty(propertyName)
|
||||
? describeValueOf(propertyName, source, resolver) : null));
|
||||
getPropertySourcesAsMap().forEach((sourceName, source) -> propertySources.put(sourceName,
|
||||
source.containsProperty(propertyName) ? describeValueOf(propertyName, source, resolver) : null));
|
||||
return propertySources;
|
||||
}
|
||||
|
||||
private PropertySourceDescriptor describeSource(String sourceName,
|
||||
EnumerablePropertySource<?> source, PlaceholdersResolver resolver,
|
||||
Predicate<String> namePredicate) {
|
||||
private PropertySourceDescriptor describeSource(String sourceName, EnumerablePropertySource<?> source,
|
||||
PlaceholdersResolver resolver, Predicate<String> namePredicate) {
|
||||
Map<String, PropertyValueDescriptor> properties = new LinkedHashMap<>();
|
||||
Stream.of(source.getPropertyNames()).filter(namePredicate).forEach(
|
||||
(name) -> properties.put(name, describeValueOf(name, source, resolver)));
|
||||
Stream.of(source.getPropertyNames()).filter(namePredicate)
|
||||
.forEach((name) -> properties.put(name, describeValueOf(name, source, resolver)));
|
||||
return new PropertySourceDescriptor(sourceName, properties);
|
||||
}
|
||||
|
||||
@@ -153,8 +141,7 @@ public class EnvironmentEndpoint {
|
||||
private PropertyValueDescriptor describeValueOf(String name, PropertySource<?> source,
|
||||
PlaceholdersResolver resolver) {
|
||||
Object resolved = resolver.resolvePlaceholders(source.getProperty(name));
|
||||
String origin = ((source instanceof OriginLookup)
|
||||
? getOrigin((OriginLookup<Object>) source, name) : null);
|
||||
String origin = ((source instanceof OriginLookup) ? getOrigin((OriginLookup<Object>) source, name) : null);
|
||||
return new PropertyValueDescriptor(sanitize(name, resolved), origin);
|
||||
}
|
||||
|
||||
@@ -164,15 +151,13 @@ public class EnvironmentEndpoint {
|
||||
}
|
||||
|
||||
private PlaceholdersResolver getResolver() {
|
||||
return new PropertySourcesPlaceholdersSanitizingResolver(getPropertySources(),
|
||||
this.sanitizer);
|
||||
return new PropertySourcesPlaceholdersSanitizingResolver(getPropertySources(), this.sanitizer);
|
||||
}
|
||||
|
||||
private Map<String, PropertySource<?>> getPropertySourcesAsMap() {
|
||||
Map<String, PropertySource<?>> map = new LinkedHashMap<>();
|
||||
for (PropertySource<?> source : getPropertySources()) {
|
||||
if (!ConfigurationPropertySources
|
||||
.isAttachedConfigurationPropertySource(source)) {
|
||||
if (!ConfigurationPropertySources.isAttachedConfigurationPropertySource(source)) {
|
||||
extract("", map, source);
|
||||
}
|
||||
}
|
||||
@@ -186,11 +171,9 @@ public class EnvironmentEndpoint {
|
||||
return new StandardEnvironment().getPropertySources();
|
||||
}
|
||||
|
||||
private void extract(String root, Map<String, PropertySource<?>> map,
|
||||
PropertySource<?> source) {
|
||||
private void extract(String root, Map<String, PropertySource<?>> map, PropertySource<?> source) {
|
||||
if (source instanceof CompositePropertySource) {
|
||||
for (PropertySource<?> nest : ((CompositePropertySource) source)
|
||||
.getPropertySources()) {
|
||||
for (PropertySource<?> nest : ((CompositePropertySource) source).getPropertySources()) {
|
||||
extract(source.getName() + ":", map, nest);
|
||||
}
|
||||
}
|
||||
@@ -207,17 +190,13 @@ public class EnvironmentEndpoint {
|
||||
* {@link PropertySourcesPlaceholdersResolver} that sanitizes sensitive placeholders
|
||||
* if present.
|
||||
*/
|
||||
private static class PropertySourcesPlaceholdersSanitizingResolver
|
||||
extends PropertySourcesPlaceholdersResolver {
|
||||
private static class PropertySourcesPlaceholdersSanitizingResolver extends PropertySourcesPlaceholdersResolver {
|
||||
|
||||
private final Sanitizer sanitizer;
|
||||
|
||||
PropertySourcesPlaceholdersSanitizingResolver(Iterable<PropertySource<?>> sources,
|
||||
Sanitizer sanitizer) {
|
||||
super(sources,
|
||||
new PropertyPlaceholderHelper(SystemPropertyUtils.PLACEHOLDER_PREFIX,
|
||||
SystemPropertyUtils.PLACEHOLDER_SUFFIX,
|
||||
SystemPropertyUtils.VALUE_SEPARATOR, true));
|
||||
PropertySourcesPlaceholdersSanitizingResolver(Iterable<PropertySource<?>> sources, Sanitizer sanitizer) {
|
||||
super(sources, new PropertyPlaceholderHelper(SystemPropertyUtils.PLACEHOLDER_PREFIX,
|
||||
SystemPropertyUtils.PLACEHOLDER_SUFFIX, SystemPropertyUtils.VALUE_SEPARATOR, true));
|
||||
this.sanitizer = sanitizer;
|
||||
}
|
||||
|
||||
@@ -241,8 +220,7 @@ public class EnvironmentEndpoint {
|
||||
|
||||
private final List<PropertySourceDescriptor> propertySources;
|
||||
|
||||
private EnvironmentDescriptor(List<String> activeProfiles,
|
||||
List<PropertySourceDescriptor> propertySources) {
|
||||
private EnvironmentDescriptor(List<String> activeProfiles, List<PropertySourceDescriptor> propertySources) {
|
||||
this.activeProfiles = activeProfiles;
|
||||
this.propertySources = propertySources;
|
||||
}
|
||||
@@ -269,8 +247,7 @@ public class EnvironmentEndpoint {
|
||||
|
||||
private final List<PropertySourceEntryDescriptor> propertySources;
|
||||
|
||||
private EnvironmentEntryDescriptor(PropertySummaryDescriptor property,
|
||||
List<String> activeProfiles,
|
||||
private EnvironmentEntryDescriptor(PropertySummaryDescriptor property, List<String> activeProfiles,
|
||||
List<PropertySourceEntryDescriptor> propertySources) {
|
||||
this.property = property;
|
||||
this.activeProfiles = activeProfiles;
|
||||
@@ -325,8 +302,7 @@ public class EnvironmentEndpoint {
|
||||
|
||||
private final Map<String, PropertyValueDescriptor> properties;
|
||||
|
||||
private PropertySourceDescriptor(String name,
|
||||
Map<String, PropertyValueDescriptor> properties) {
|
||||
private PropertySourceDescriptor(String name, Map<String, PropertyValueDescriptor> properties) {
|
||||
this.name = name;
|
||||
this.properties = properties;
|
||||
}
|
||||
@@ -351,8 +327,7 @@ public class EnvironmentEndpoint {
|
||||
|
||||
private final PropertyValueDescriptor property;
|
||||
|
||||
private PropertySourceEntryDescriptor(String name,
|
||||
PropertyValueDescriptor property) {
|
||||
private PropertySourceEntryDescriptor(String name, PropertyValueDescriptor property) {
|
||||
this.name = name;
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -38,8 +38,7 @@ public class EnvironmentEndpointWebExtension {
|
||||
}
|
||||
|
||||
@ReadOperation
|
||||
public WebEndpointResponse<EnvironmentEntryDescriptor> environmentEntry(
|
||||
@Selector String toMatch) {
|
||||
public WebEndpointResponse<EnvironmentEntryDescriptor> environmentEntry(@Selector String toMatch) {
|
||||
EnvironmentEntryDescriptor descriptor = this.delegate.environmentEntry(toMatch);
|
||||
return new WebEndpointResponse<>(descriptor, getStatus(descriptor));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -57,11 +57,11 @@ public class FlywayEndpoint {
|
||||
Map<String, ContextFlywayBeans> contextFlywayBeans = new HashMap<>();
|
||||
while (target != null) {
|
||||
Map<String, FlywayDescriptor> flywayBeans = new HashMap<>();
|
||||
target.getBeansOfType(Flyway.class).forEach((name, flyway) -> flywayBeans
|
||||
.put(name, new FlywayDescriptor(flyway.info().all())));
|
||||
target.getBeansOfType(Flyway.class)
|
||||
.forEach((name, flyway) -> flywayBeans.put(name, new FlywayDescriptor(flyway.info().all())));
|
||||
ApplicationContext parent = target.getParent();
|
||||
contextFlywayBeans.put(target.getId(), new ContextFlywayBeans(flywayBeans,
|
||||
(parent != null) ? parent.getId() : null));
|
||||
contextFlywayBeans.put(target.getId(),
|
||||
new ContextFlywayBeans(flywayBeans, (parent != null) ? parent.getId() : null));
|
||||
target = parent;
|
||||
}
|
||||
return new ApplicationFlywayBeans(contextFlywayBeans);
|
||||
@@ -95,8 +95,7 @@ public class FlywayEndpoint {
|
||||
|
||||
private final String parentId;
|
||||
|
||||
private ContextFlywayBeans(Map<String, FlywayDescriptor> flywayBeans,
|
||||
String parentId) {
|
||||
private ContextFlywayBeans(Map<String, FlywayDescriptor> flywayBeans, String parentId) {
|
||||
this.flywayBeans = flywayBeans;
|
||||
this.parentId = parentId;
|
||||
}
|
||||
@@ -119,8 +118,7 @@ public class FlywayEndpoint {
|
||||
private final List<FlywayMigration> migrations;
|
||||
|
||||
private FlywayDescriptor(MigrationInfo[] migrations) {
|
||||
this.migrations = Stream.of(migrations).map(FlywayMigration::new)
|
||||
.collect(Collectors.toList());
|
||||
this.migrations = Stream.of(migrations).map(FlywayMigration::new).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public FlywayDescriptor(List<FlywayMigration> migrations) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -33,8 +33,7 @@ public abstract class AbstractHealthAggregator implements HealthAggregator {
|
||||
|
||||
@Override
|
||||
public final Health aggregate(Map<String, Health> healths) {
|
||||
List<Status> statusCandidates = healths.values().stream().map(Health::getStatus)
|
||||
.collect(Collectors.toList());
|
||||
List<Status> statusCandidates = healths.values().stream().map(Health::getStatus).collect(Collectors.toList());
|
||||
Status status = aggregateStatus(statusCandidates);
|
||||
Map<String, Object> details = aggregateDetails(healths);
|
||||
return new Health.Builder(status, details).build();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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,8 @@ public abstract class AbstractHealthIndicator implements HealthIndicator {
|
||||
* @param healthCheckFailedMessage the message to log on health check failure
|
||||
* @since 2.0.0
|
||||
*/
|
||||
protected AbstractHealthIndicator(
|
||||
Function<Exception, String> healthCheckFailedMessage) {
|
||||
Assert.notNull(healthCheckFailedMessage,
|
||||
"HealthCheckFailedMessage must not be null");
|
||||
protected AbstractHealthIndicator(Function<Exception, String> healthCheckFailedMessage) {
|
||||
Assert.notNull(healthCheckFailedMessage, "HealthCheckFailedMessage must not be null");
|
||||
this.healthCheckFailedMessage = healthCheckFailedMessage;
|
||||
}
|
||||
|
||||
@@ -86,8 +84,7 @@ public abstract class AbstractHealthIndicator implements HealthIndicator {
|
||||
catch (Exception ex) {
|
||||
if (this.logger.isWarnEnabled()) {
|
||||
String message = this.healthCheckFailedMessage.apply(ex);
|
||||
this.logger.warn(StringUtils.hasText(message) ? message : DEFAULT_MESSAGE,
|
||||
ex);
|
||||
this.logger.warn(StringUtils.hasText(message) ? message : DEFAULT_MESSAGE, ex);
|
||||
}
|
||||
builder.down(ex);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -50,8 +50,7 @@ public class CompositeHealthIndicator implements HealthIndicator {
|
||||
* @param indicators a map of {@link HealthIndicator HealthIndicators} with the key
|
||||
* being used as an indicator name.
|
||||
*/
|
||||
public CompositeHealthIndicator(HealthAggregator healthAggregator,
|
||||
Map<String, HealthIndicator> indicators) {
|
||||
public CompositeHealthIndicator(HealthAggregator healthAggregator, Map<String, HealthIndicator> indicators) {
|
||||
this(healthAggregator, new DefaultHealthIndicatorRegistry(indicators));
|
||||
}
|
||||
|
||||
@@ -61,8 +60,7 @@ public class CompositeHealthIndicator implements HealthIndicator {
|
||||
* @param healthAggregator the health aggregator
|
||||
* @param registry the registry of {@link HealthIndicator HealthIndicators}.
|
||||
*/
|
||||
public CompositeHealthIndicator(HealthAggregator healthAggregator,
|
||||
HealthIndicatorRegistry registry) {
|
||||
public CompositeHealthIndicator(HealthAggregator healthAggregator, HealthIndicatorRegistry registry) {
|
||||
this.aggregator = healthAggregator;
|
||||
this.registry = registry;
|
||||
}
|
||||
@@ -93,8 +91,7 @@ public class CompositeHealthIndicator implements HealthIndicator {
|
||||
@Override
|
||||
public Health health() {
|
||||
Map<String, Health> healths = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, HealthIndicator> entry : this.registry.getAll()
|
||||
.entrySet()) {
|
||||
for (Map.Entry<String, HealthIndicator> entry : this.registry.getAll().entrySet()) {
|
||||
healths.put(entry.getKey(), entry.getValue().health());
|
||||
}
|
||||
return this.aggregator.aggregate(healths);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -38,8 +38,7 @@ public class CompositeHealthIndicatorFactory {
|
||||
this(new HealthIndicatorNameFactory());
|
||||
}
|
||||
|
||||
public CompositeHealthIndicatorFactory(
|
||||
Function<String, String> healthIndicatorNameFactory) {
|
||||
public CompositeHealthIndicatorFactory(Function<String, String> healthIndicatorNameFactory) {
|
||||
this.healthIndicatorNameFactory = healthIndicatorNameFactory;
|
||||
}
|
||||
|
||||
@@ -50,15 +49,12 @@ public class CompositeHealthIndicatorFactory {
|
||||
* @return a {@link HealthIndicator} that delegates to the specified
|
||||
* {@code healthIndicators}.
|
||||
*/
|
||||
public CompositeHealthIndicator createHealthIndicator(
|
||||
HealthAggregator healthAggregator,
|
||||
public CompositeHealthIndicator createHealthIndicator(HealthAggregator healthAggregator,
|
||||
Map<String, HealthIndicator> healthIndicators) {
|
||||
Assert.notNull(healthAggregator, "HealthAggregator must not be null");
|
||||
Assert.notNull(healthIndicators, "HealthIndicators must not be null");
|
||||
HealthIndicatorRegistryFactory factory = new HealthIndicatorRegistryFactory(
|
||||
this.healthIndicatorNameFactory);
|
||||
return new CompositeHealthIndicator(healthAggregator,
|
||||
factory.createHealthIndicatorRegistry(healthIndicators));
|
||||
HealthIndicatorRegistryFactory factory = new HealthIndicatorRegistryFactory(this.healthIndicatorNameFactory);
|
||||
return new CompositeHealthIndicator(healthAggregator, factory.createHealthIndicatorRegistry(healthIndicators));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -82,8 +82,8 @@ public class CompositeReactiveHealthIndicator implements ReactiveHealthIndicator
|
||||
ReactiveHealthIndicatorRegistry registry) {
|
||||
this.registry = registry;
|
||||
this.healthAggregator = healthAggregator;
|
||||
this.timeoutCompose = (mono) -> (this.timeout != null) ? mono.timeout(
|
||||
Duration.ofMillis(this.timeout), Mono.just(this.timeoutHealth)) : mono;
|
||||
this.timeoutCompose = (mono) -> (this.timeout != null)
|
||||
? mono.timeout(Duration.ofMillis(this.timeout), Mono.just(this.timeoutHealth)) : mono;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,8 +97,7 @@ public class CompositeReactiveHealthIndicator implements ReactiveHealthIndicator
|
||||
* {@link ReactiveHealthIndicatorRegistry#register(String, ReactiveHealthIndicator)}
|
||||
*/
|
||||
@Deprecated
|
||||
public CompositeReactiveHealthIndicator addHealthIndicator(String name,
|
||||
ReactiveHealthIndicator indicator) {
|
||||
public CompositeReactiveHealthIndicator addHealthIndicator(String name, ReactiveHealthIndicator indicator) {
|
||||
this.registry.register(name, indicator);
|
||||
return this;
|
||||
}
|
||||
@@ -112,11 +111,9 @@ public class CompositeReactiveHealthIndicator implements ReactiveHealthIndicator
|
||||
* {@code timeout}
|
||||
* @return this instance
|
||||
*/
|
||||
public CompositeReactiveHealthIndicator timeoutStrategy(long timeout,
|
||||
Health timeoutHealth) {
|
||||
public CompositeReactiveHealthIndicator timeoutStrategy(long timeout, Health timeoutHealth) {
|
||||
this.timeout = timeout;
|
||||
this.timeoutHealth = (timeoutHealth != null) ? timeoutHealth
|
||||
: Health.unknown().build();
|
||||
this.timeoutHealth = (timeoutHealth != null) ? timeoutHealth : Health.unknown().build();
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -126,11 +123,9 @@ public class CompositeReactiveHealthIndicator implements ReactiveHealthIndicator
|
||||
|
||||
@Override
|
||||
public Mono<Health> health() {
|
||||
return Flux.fromIterable(this.registry.getAll().entrySet())
|
||||
.flatMap((entry) -> Mono.zip(Mono.just(entry.getKey()),
|
||||
entry.getValue().health().compose(this.timeoutCompose)))
|
||||
.collectMap(Tuple2::getT1, Tuple2::getT2)
|
||||
.map(this.healthAggregator::aggregate);
|
||||
return Flux.fromIterable(this.registry.getAll().entrySet()).flatMap(
|
||||
(entry) -> Mono.zip(Mono.just(entry.getKey()), entry.getValue().health().compose(this.timeoutCompose)))
|
||||
.collectMap(Tuple2::getT1, Tuple2::getT2).map(this.healthAggregator::aggregate);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -34,8 +34,7 @@ public class CompositeReactiveHealthIndicatorFactory {
|
||||
|
||||
private final Function<String, String> healthIndicatorNameFactory;
|
||||
|
||||
public CompositeReactiveHealthIndicatorFactory(
|
||||
Function<String, String> healthIndicatorNameFactory) {
|
||||
public CompositeReactiveHealthIndicatorFactory(Function<String, String> healthIndicatorNameFactory) {
|
||||
this.healthIndicatorNameFactory = healthIndicatorNameFactory;
|
||||
}
|
||||
|
||||
@@ -56,18 +55,15 @@ public class CompositeReactiveHealthIndicatorFactory {
|
||||
* @return a {@link ReactiveHealthIndicator} that delegates to the specified
|
||||
* {@code reactiveHealthIndicators}.
|
||||
*/
|
||||
public CompositeReactiveHealthIndicator createReactiveHealthIndicator(
|
||||
HealthAggregator healthAggregator,
|
||||
public CompositeReactiveHealthIndicator createReactiveHealthIndicator(HealthAggregator healthAggregator,
|
||||
Map<String, ReactiveHealthIndicator> reactiveHealthIndicators,
|
||||
Map<String, HealthIndicator> healthIndicators) {
|
||||
Assert.notNull(healthAggregator, "HealthAggregator must not be null");
|
||||
Assert.notNull(reactiveHealthIndicators,
|
||||
"ReactiveHealthIndicators must not be null");
|
||||
Assert.notNull(reactiveHealthIndicators, "ReactiveHealthIndicators must not be null");
|
||||
ReactiveHealthIndicatorRegistryFactory factory = new ReactiveHealthIndicatorRegistryFactory(
|
||||
this.healthIndicatorNameFactory);
|
||||
return new CompositeReactiveHealthIndicator(healthAggregator,
|
||||
factory.createReactiveHealthIndicatorRegistry(reactiveHealthIndicators,
|
||||
healthIndicators));
|
||||
factory.createReactiveHealthIndicatorRegistry(reactiveHealthIndicators, healthIndicators));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -57,11 +57,9 @@ public class DefaultHealthIndicatorRegistry implements HealthIndicatorRegistry {
|
||||
Assert.notNull(healthIndicator, "HealthIndicator must not be null");
|
||||
Assert.notNull(name, "Name must not be null");
|
||||
synchronized (this.monitor) {
|
||||
HealthIndicator existing = this.healthIndicators.putIfAbsent(name,
|
||||
healthIndicator);
|
||||
HealthIndicator existing = this.healthIndicators.putIfAbsent(name, healthIndicator);
|
||||
if (existing != null) {
|
||||
throw new IllegalStateException(
|
||||
"HealthIndicator with name '" + name + "' already registered");
|
||||
throw new IllegalStateException("HealthIndicator with name '" + name + "' already registered");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,8 +83,7 @@ public class DefaultHealthIndicatorRegistry implements HealthIndicatorRegistry {
|
||||
@Override
|
||||
public Map<String, HealthIndicator> getAll() {
|
||||
synchronized (this.monitor) {
|
||||
return Collections
|
||||
.unmodifiableMap(new LinkedHashMap<>(this.healthIndicators));
|
||||
return Collections.unmodifiableMap(new LinkedHashMap<>(this.healthIndicators));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -29,8 +29,7 @@ import org.springframework.util.Assert;
|
||||
* @author Stephane Nicoll
|
||||
* @since 2.1.0
|
||||
*/
|
||||
public class DefaultReactiveHealthIndicatorRegistry
|
||||
implements ReactiveHealthIndicatorRegistry {
|
||||
public class DefaultReactiveHealthIndicatorRegistry implements ReactiveHealthIndicatorRegistry {
|
||||
|
||||
private final Object monitor = new Object();
|
||||
|
||||
@@ -49,8 +48,7 @@ public class DefaultReactiveHealthIndicatorRegistry
|
||||
* @param healthIndicators a map of {@link HealthIndicator}s with the key being used
|
||||
* as an indicator name.
|
||||
*/
|
||||
public DefaultReactiveHealthIndicatorRegistry(
|
||||
Map<String, ReactiveHealthIndicator> healthIndicators) {
|
||||
public DefaultReactiveHealthIndicatorRegistry(Map<String, ReactiveHealthIndicator> healthIndicators) {
|
||||
Assert.notNull(healthIndicators, "HealthIndicators must not be null");
|
||||
this.healthIndicators = new LinkedHashMap<>(healthIndicators);
|
||||
}
|
||||
@@ -60,11 +58,9 @@ public class DefaultReactiveHealthIndicatorRegistry
|
||||
Assert.notNull(healthIndicator, "HealthIndicator must not be null");
|
||||
Assert.notNull(name, "Name must not be null");
|
||||
synchronized (this.monitor) {
|
||||
ReactiveHealthIndicator existing = this.healthIndicators.putIfAbsent(name,
|
||||
healthIndicator);
|
||||
ReactiveHealthIndicator existing = this.healthIndicators.putIfAbsent(name, healthIndicator);
|
||||
if (existing != null) {
|
||||
throw new IllegalStateException(
|
||||
"HealthIndicator with name '" + name + "' already registered");
|
||||
throw new IllegalStateException("HealthIndicator with name '" + name + "' already registered");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -88,8 +84,7 @@ public class DefaultReactiveHealthIndicatorRegistry
|
||||
@Override
|
||||
public Map<String, ReactiveHealthIndicator> getAll() {
|
||||
synchronized (this.monitor) {
|
||||
return Collections
|
||||
.unmodifiableMap(new LinkedHashMap<>(this.healthIndicators));
|
||||
return Collections.unmodifiableMap(new LinkedHashMap<>(this.healthIndicators));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -58,8 +58,7 @@ public class HealthEndpoint {
|
||||
*/
|
||||
@ReadOperation
|
||||
public Health healthForComponent(@Selector String component) {
|
||||
HealthIndicator indicator = getNestedHealthIndicator(this.healthIndicator,
|
||||
component);
|
||||
HealthIndicator indicator = getNestedHealthIndicator(this.healthIndicator, component);
|
||||
return (indicator != null) ? indicator.health() : null;
|
||||
}
|
||||
|
||||
@@ -72,16 +71,13 @@ public class HealthEndpoint {
|
||||
* @return the {@link Health} for the component instance of {@code null}
|
||||
*/
|
||||
@ReadOperation
|
||||
public Health healthForComponentInstance(@Selector String component,
|
||||
@Selector String instance) {
|
||||
HealthIndicator indicator = getNestedHealthIndicator(this.healthIndicator,
|
||||
component);
|
||||
public Health healthForComponentInstance(@Selector String component, @Selector String instance) {
|
||||
HealthIndicator indicator = getNestedHealthIndicator(this.healthIndicator, component);
|
||||
HealthIndicator nestedIndicator = getNestedHealthIndicator(indicator, instance);
|
||||
return (nestedIndicator != null) ? nestedIndicator.health() : null;
|
||||
}
|
||||
|
||||
private HealthIndicator getNestedHealthIndicator(HealthIndicator healthIndicator,
|
||||
String name) {
|
||||
private HealthIndicator getNestedHealthIndicator(HealthIndicator healthIndicator, String name) {
|
||||
if (healthIndicator instanceof CompositeHealthIndicator) {
|
||||
return ((CompositeHealthIndicator) healthIndicator).getRegistry().get(name);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -43,8 +43,7 @@ public class HealthEndpointWebExtension {
|
||||
|
||||
private final HealthWebEndpointResponseMapper responseMapper;
|
||||
|
||||
public HealthEndpointWebExtension(HealthEndpoint delegate,
|
||||
HealthWebEndpointResponseMapper responseMapper) {
|
||||
public HealthEndpointWebExtension(HealthEndpoint delegate, HealthWebEndpointResponseMapper responseMapper) {
|
||||
this.delegate = delegate;
|
||||
this.responseMapper = responseMapper;
|
||||
}
|
||||
@@ -55,25 +54,20 @@ public class HealthEndpointWebExtension {
|
||||
}
|
||||
|
||||
@ReadOperation
|
||||
public WebEndpointResponse<Health> healthForComponent(SecurityContext securityContext,
|
||||
@Selector String component) {
|
||||
public WebEndpointResponse<Health> healthForComponent(SecurityContext securityContext, @Selector String component) {
|
||||
Supplier<Health> health = () -> this.delegate.healthForComponent(component);
|
||||
return this.responseMapper.mapDetails(health, securityContext);
|
||||
}
|
||||
|
||||
@ReadOperation
|
||||
public WebEndpointResponse<Health> healthForComponentInstance(
|
||||
SecurityContext securityContext, @Selector String component,
|
||||
@Selector String instance) {
|
||||
Supplier<Health> health = () -> this.delegate
|
||||
.healthForComponentInstance(component, instance);
|
||||
public WebEndpointResponse<Health> healthForComponentInstance(SecurityContext securityContext,
|
||||
@Selector String component, @Selector String instance) {
|
||||
Supplier<Health> health = () -> this.delegate.healthForComponentInstance(component, instance);
|
||||
return this.responseMapper.mapDetails(health, securityContext);
|
||||
}
|
||||
|
||||
public WebEndpointResponse<Health> getHealth(SecurityContext securityContext,
|
||||
ShowDetails showDetails) {
|
||||
return this.responseMapper.map(this.delegate.health(), securityContext,
|
||||
showDetails);
|
||||
public WebEndpointResponse<Health> getHealth(SecurityContext securityContext, ShowDetails showDetails) {
|
||||
return this.responseMapper.map(this.delegate.health(), securityContext, showDetails);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -31,8 +31,7 @@ public class HealthIndicatorRegistryFactory {
|
||||
|
||||
private final Function<String, String> healthIndicatorNameFactory;
|
||||
|
||||
public HealthIndicatorRegistryFactory(
|
||||
Function<String, String> healthIndicatorNameFactory) {
|
||||
public HealthIndicatorRegistryFactory(Function<String, String> healthIndicatorNameFactory) {
|
||||
this.healthIndicatorNameFactory = healthIndicatorNameFactory;
|
||||
}
|
||||
|
||||
@@ -46,8 +45,7 @@ public class HealthIndicatorRegistryFactory {
|
||||
* @return a {@link HealthIndicator} that delegates to the specified
|
||||
* {@code healthIndicators}.
|
||||
*/
|
||||
public HealthIndicatorRegistry createHealthIndicatorRegistry(
|
||||
Map<String, HealthIndicator> healthIndicators) {
|
||||
public HealthIndicatorRegistry createHealthIndicatorRegistry(Map<String, HealthIndicator> healthIndicators) {
|
||||
Assert.notNull(healthIndicators, "HealthIndicators must not be null");
|
||||
return initialize(new DefaultHealthIndicatorRegistry(), healthIndicators);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -42,8 +42,7 @@ public class HealthStatusHttpMapper {
|
||||
|
||||
private void setupDefaultStatusMapping() {
|
||||
addStatusMapping(Status.DOWN, WebEndpointResponse.STATUS_SERVICE_UNAVAILABLE);
|
||||
addStatusMapping(Status.OUT_OF_SERVICE,
|
||||
WebEndpointResponse.STATUS_SERVICE_UNAVAILABLE);
|
||||
addStatusMapping(Status.OUT_OF_SERVICE, WebEndpointResponse.STATUS_SERVICE_UNAVAILABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,9 +102,8 @@ public class HealthStatusHttpMapper {
|
||||
String code = getUniformValue(status.getCode());
|
||||
if (code != null) {
|
||||
return this.statusMapping.entrySet().stream()
|
||||
.filter((entry) -> code.equals(getUniformValue(entry.getKey())))
|
||||
.map(Map.Entry::getValue).findFirst()
|
||||
.orElse(WebEndpointResponse.STATUS_OK);
|
||||
.filter((entry) -> code.equals(getUniformValue(entry.getKey()))).map(Map.Entry::getValue)
|
||||
.findFirst().orElse(WebEndpointResponse.STATUS_OK);
|
||||
}
|
||||
return WebEndpointResponse.STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ public class HealthWebEndpointResponseMapper {
|
||||
|
||||
private final Set<String> authorizedRoles;
|
||||
|
||||
public HealthWebEndpointResponseMapper(HealthStatusHttpMapper statusHttpMapper,
|
||||
ShowDetails showDetails, Set<String> authorizedRoles) {
|
||||
public HealthWebEndpointResponseMapper(HealthStatusHttpMapper statusHttpMapper, ShowDetails showDetails,
|
||||
Set<String> authorizedRoles) {
|
||||
this.statusHttpMapper = statusHttpMapper;
|
||||
this.showDetails = showDetails;
|
||||
this.authorizedRoles = authorizedRoles;
|
||||
@@ -55,8 +55,7 @@ public class HealthWebEndpointResponseMapper {
|
||||
* @param securityContext the security context
|
||||
* @return the mapped response
|
||||
*/
|
||||
public WebEndpointResponse<Health> mapDetails(Supplier<Health> health,
|
||||
SecurityContext securityContext) {
|
||||
public WebEndpointResponse<Health> mapDetails(Supplier<Health> health, SecurityContext securityContext) {
|
||||
if (canSeeDetails(securityContext, this.showDetails)) {
|
||||
Health healthDetails = health.get();
|
||||
if (healthDetails != null) {
|
||||
@@ -73,8 +72,7 @@ public class HealthWebEndpointResponseMapper {
|
||||
* @param securityContext the security context
|
||||
* @return the mapped response
|
||||
*/
|
||||
public WebEndpointResponse<Health> map(Health health,
|
||||
SecurityContext securityContext) {
|
||||
public WebEndpointResponse<Health> map(Health health, SecurityContext securityContext) {
|
||||
return map(health, securityContext, this.showDetails);
|
||||
}
|
||||
|
||||
@@ -86,8 +84,7 @@ public class HealthWebEndpointResponseMapper {
|
||||
* @param showDetails when to show details in the response
|
||||
* @return the mapped response
|
||||
*/
|
||||
public WebEndpointResponse<Health> map(Health health, SecurityContext securityContext,
|
||||
ShowDetails showDetails) {
|
||||
public WebEndpointResponse<Health> map(Health health, SecurityContext securityContext, ShowDetails showDetails) {
|
||||
if (!canSeeDetails(securityContext, showDetails)) {
|
||||
health = Health.status(health.getStatus()).build();
|
||||
}
|
||||
@@ -99,12 +96,9 @@ public class HealthWebEndpointResponseMapper {
|
||||
return new WebEndpointResponse<>(health, status);
|
||||
}
|
||||
|
||||
private boolean canSeeDetails(SecurityContext securityContext,
|
||||
ShowDetails showDetails) {
|
||||
if (showDetails == ShowDetails.NEVER
|
||||
|| (showDetails == ShowDetails.WHEN_AUTHORIZED
|
||||
&& (securityContext.getPrincipal() == null
|
||||
|| !isUserInRole(securityContext)))) {
|
||||
private boolean canSeeDetails(SecurityContext securityContext, ShowDetails showDetails) {
|
||||
if (showDetails == ShowDetails.NEVER || (showDetails == ShowDetails.WHEN_AUTHORIZED
|
||||
&& (securityContext.getPrincipal() == null || !isUserInRole(securityContext)))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -45,48 +45,38 @@ public class ReactiveHealthEndpointWebExtension {
|
||||
|
||||
@ReadOperation
|
||||
public Mono<WebEndpointResponse<Health>> health(SecurityContext securityContext) {
|
||||
return this.delegate.health()
|
||||
.map((health) -> this.responseMapper.map(health, securityContext));
|
||||
return this.delegate.health().map((health) -> this.responseMapper.map(health, securityContext));
|
||||
}
|
||||
|
||||
@ReadOperation
|
||||
public Mono<WebEndpointResponse<Health>> healthForComponent(
|
||||
SecurityContext securityContext, @Selector String component) {
|
||||
return responseFromIndicator(getNestedHealthIndicator(this.delegate, component),
|
||||
securityContext);
|
||||
public Mono<WebEndpointResponse<Health>> healthForComponent(SecurityContext securityContext,
|
||||
@Selector String component) {
|
||||
return responseFromIndicator(getNestedHealthIndicator(this.delegate, component), securityContext);
|
||||
}
|
||||
|
||||
@ReadOperation
|
||||
public Mono<WebEndpointResponse<Health>> healthForComponentInstance(
|
||||
SecurityContext securityContext, @Selector String component,
|
||||
@Selector String instance) {
|
||||
ReactiveHealthIndicator indicator = getNestedHealthIndicator(this.delegate,
|
||||
component);
|
||||
public Mono<WebEndpointResponse<Health>> healthForComponentInstance(SecurityContext securityContext,
|
||||
@Selector String component, @Selector String instance) {
|
||||
ReactiveHealthIndicator indicator = getNestedHealthIndicator(this.delegate, component);
|
||||
if (indicator != null) {
|
||||
indicator = getNestedHealthIndicator(indicator, instance);
|
||||
}
|
||||
return responseFromIndicator(indicator, securityContext);
|
||||
}
|
||||
|
||||
public Mono<WebEndpointResponse<Health>> health(SecurityContext securityContext,
|
||||
ShowDetails showDetails) {
|
||||
return this.delegate.health().map((health) -> this.responseMapper.map(health,
|
||||
securityContext, showDetails));
|
||||
public Mono<WebEndpointResponse<Health>> health(SecurityContext securityContext, ShowDetails showDetails) {
|
||||
return this.delegate.health().map((health) -> this.responseMapper.map(health, securityContext, showDetails));
|
||||
}
|
||||
|
||||
private Mono<WebEndpointResponse<Health>> responseFromIndicator(
|
||||
ReactiveHealthIndicator indicator, SecurityContext securityContext) {
|
||||
private Mono<WebEndpointResponse<Health>> responseFromIndicator(ReactiveHealthIndicator indicator,
|
||||
SecurityContext securityContext) {
|
||||
return (indicator != null)
|
||||
? indicator.health()
|
||||
.map((health) -> this.responseMapper.map(health, securityContext))
|
||||
: Mono.empty();
|
||||
? indicator.health().map((health) -> this.responseMapper.map(health, securityContext)) : Mono.empty();
|
||||
}
|
||||
|
||||
private ReactiveHealthIndicator getNestedHealthIndicator(
|
||||
ReactiveHealthIndicator healthIndicator, String name) {
|
||||
private ReactiveHealthIndicator getNestedHealthIndicator(ReactiveHealthIndicator healthIndicator, String name) {
|
||||
if (healthIndicator instanceof CompositeReactiveHealthIndicator) {
|
||||
return ((CompositeReactiveHealthIndicator) healthIndicator).getRegistry()
|
||||
.get(name);
|
||||
return ((CompositeReactiveHealthIndicator) healthIndicator).getRegistry().get(name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -33,8 +33,7 @@ public class ReactiveHealthIndicatorRegistryFactory {
|
||||
|
||||
private final Function<String, String> healthIndicatorNameFactory;
|
||||
|
||||
public ReactiveHealthIndicatorRegistryFactory(
|
||||
Function<String, String> healthIndicatorNameFactory) {
|
||||
public ReactiveHealthIndicatorRegistryFactory(Function<String, String> healthIndicatorNameFactory) {
|
||||
this.healthIndicatorNameFactory = healthIndicatorNameFactory;
|
||||
}
|
||||
|
||||
@@ -57,35 +56,29 @@ public class ReactiveHealthIndicatorRegistryFactory {
|
||||
public ReactiveHealthIndicatorRegistry createReactiveHealthIndicatorRegistry(
|
||||
Map<String, ReactiveHealthIndicator> reactiveHealthIndicators,
|
||||
Map<String, HealthIndicator> healthIndicators) {
|
||||
Assert.notNull(reactiveHealthIndicators,
|
||||
"ReactiveHealthIndicators must not be null");
|
||||
return initialize(new DefaultReactiveHealthIndicatorRegistry(),
|
||||
reactiveHealthIndicators, healthIndicators);
|
||||
Assert.notNull(reactiveHealthIndicators, "ReactiveHealthIndicators must not be null");
|
||||
return initialize(new DefaultReactiveHealthIndicatorRegistry(), reactiveHealthIndicators, healthIndicators);
|
||||
}
|
||||
|
||||
protected <T extends ReactiveHealthIndicatorRegistry> T initialize(T registry,
|
||||
Map<String, ReactiveHealthIndicator> reactiveHealthIndicators,
|
||||
Map<String, HealthIndicator> healthIndicators) {
|
||||
merge(reactiveHealthIndicators, healthIndicators)
|
||||
.forEach((beanName, indicator) -> {
|
||||
String name = this.healthIndicatorNameFactory.apply(beanName);
|
||||
registry.register(name, indicator);
|
||||
});
|
||||
merge(reactiveHealthIndicators, healthIndicators).forEach((beanName, indicator) -> {
|
||||
String name = this.healthIndicatorNameFactory.apply(beanName);
|
||||
registry.register(name, indicator);
|
||||
});
|
||||
return registry;
|
||||
}
|
||||
|
||||
private Map<String, ReactiveHealthIndicator> merge(
|
||||
Map<String, ReactiveHealthIndicator> reactiveHealthIndicators,
|
||||
private Map<String, ReactiveHealthIndicator> merge(Map<String, ReactiveHealthIndicator> reactiveHealthIndicators,
|
||||
Map<String, HealthIndicator> healthIndicators) {
|
||||
if (ObjectUtils.isEmpty(healthIndicators)) {
|
||||
return reactiveHealthIndicators;
|
||||
}
|
||||
Map<String, ReactiveHealthIndicator> allIndicators = new LinkedHashMap<>(
|
||||
reactiveHealthIndicators);
|
||||
Map<String, ReactiveHealthIndicator> allIndicators = new LinkedHashMap<>(reactiveHealthIndicators);
|
||||
healthIndicators.forEach((beanName, indicator) -> {
|
||||
String name = this.healthIndicatorNameFactory.apply(beanName);
|
||||
allIndicators.computeIfAbsent(name,
|
||||
(n) -> new HealthIndicatorReactiveAdapter(indicator));
|
||||
allIndicators.computeIfAbsent(name, (n) -> new HealthIndicatorReactiveAdapter(indicator));
|
||||
});
|
||||
return allIndicators;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -32,8 +32,7 @@ import org.springframework.core.env.ConfigurableEnvironment;
|
||||
*/
|
||||
public class EnvironmentInfoContributor implements InfoContributor {
|
||||
|
||||
private static final Bindable<Map<String, Object>> STRING_OBJECT_MAP = Bindable
|
||||
.mapOf(String.class, Object.class);
|
||||
private static final Bindable<Map<String, Object>> STRING_OBJECT_MAP = Bindable.mapOf(String.class, Object.class);
|
||||
|
||||
private final ConfigurableEnvironment environment;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -64,10 +64,8 @@ public class GitInfoContributor extends InfoPropertiesInfoContributor<GitPropert
|
||||
*/
|
||||
@Override
|
||||
protected void postProcessContent(Map<String, Object> content) {
|
||||
replaceValue(getNestedMap(content, "commit"), "time",
|
||||
getProperties().getCommitTime());
|
||||
replaceValue(getNestedMap(content, "build"), "time",
|
||||
getProperties().getInstant("build.time"));
|
||||
replaceValue(getNestedMap(content, "commit"), "time", getProperties().getCommitTime());
|
||||
replaceValue(getNestedMap(content, "build"), "time", getProperties().getInstant("build.time"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -62,8 +62,7 @@ public final class Info {
|
||||
public <T> T get(String id, Class<T> type) {
|
||||
Object value = get(id);
|
||||
if (value != null && type != null && !type.isInstance(value)) {
|
||||
throw new IllegalStateException("Info entry is not of required type ["
|
||||
+ type.getName() + "]: " + value);
|
||||
throw new IllegalStateException("Info entry is not of required type [" + type.getName() + "]: " + value);
|
||||
}
|
||||
return (T) value;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -36,11 +36,9 @@ import org.springframework.util.StringUtils;
|
||||
* @author Madhura Bhave
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public abstract class InfoPropertiesInfoContributor<T extends InfoProperties>
|
||||
implements InfoContributor {
|
||||
public abstract class InfoPropertiesInfoContributor<T extends InfoProperties> implements InfoContributor {
|
||||
|
||||
private static final Bindable<Map<String, Object>> STRING_OBJECT_MAP = Bindable
|
||||
.mapOf(String.class, Object.class);
|
||||
private static final Bindable<Map<String, Object>> STRING_OBJECT_MAP = Bindable.mapOf(String.class, Object.class);
|
||||
|
||||
private final T properties;
|
||||
|
||||
@@ -92,8 +90,8 @@ public abstract class InfoPropertiesInfoContributor<T extends InfoProperties>
|
||||
* @return the raw content
|
||||
*/
|
||||
protected Map<String, Object> extractContent(PropertySource<?> propertySource) {
|
||||
return new Binder(ConfigurationPropertySources.from(propertySource))
|
||||
.bind("", STRING_OBJECT_MAP).orElseGet(LinkedHashMap::new);
|
||||
return new Binder(ConfigurationPropertySources.from(propertySource)).bind("", STRING_OBJECT_MAP)
|
||||
.orElseGet(LinkedHashMap::new);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -49,8 +49,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Arthur Kalimullin
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class DataSourceHealthIndicator extends AbstractHealthIndicator
|
||||
implements InitializingBean {
|
||||
public class DataSourceHealthIndicator extends AbstractHealthIndicator implements InitializingBean {
|
||||
|
||||
private static final String DEFAULT_QUERY = "SELECT 1";
|
||||
|
||||
@@ -91,8 +90,7 @@ public class DataSourceHealthIndicator extends AbstractHealthIndicator
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.state(this.dataSource != null,
|
||||
"DataSource for DataSourceHealthIndicator must be specified");
|
||||
Assert.state(this.dataSource != null, "DataSource for DataSourceHealthIndicator must be specified");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -111,8 +109,7 @@ public class DataSourceHealthIndicator extends AbstractHealthIndicator
|
||||
String validationQuery = getValidationQuery(product);
|
||||
if (StringUtils.hasText(validationQuery)) {
|
||||
// Avoid calling getObject as it breaks MySQL on Java 7
|
||||
List<Object> results = this.jdbcTemplate.query(validationQuery,
|
||||
new SingleColumnRowMapper());
|
||||
List<Object> results = this.jdbcTemplate.query(validationQuery, new SingleColumnRowMapper());
|
||||
Object result = DataAccessUtils.requiredSingleResult(results);
|
||||
builder.withDetail("hello", result);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -51,8 +51,7 @@ public class JmsHealthIndicator extends AbstractHealthIndicator {
|
||||
protected void doHealthCheck(Health.Builder builder) throws Exception {
|
||||
try (Connection connection = this.connectionFactory.createConnection()) {
|
||||
new MonitoredConnection(connection).start();
|
||||
builder.up().withDetail("provider",
|
||||
connection.getMetaData().getJMSProviderName());
|
||||
builder.up().withDetail("provider", connection.getMetaData().getJMSProviderName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,8 +69,8 @@ public class JmsHealthIndicator extends AbstractHealthIndicator {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
if (!this.latch.await(5, TimeUnit.SECONDS)) {
|
||||
JmsHealthIndicator.this.logger.warn(
|
||||
"Connection failed to start within 5 seconds and will be closed.");
|
||||
JmsHealthIndicator.this.logger
|
||||
.warn("Connection failed to start within 5 seconds and will be closed.");
|
||||
closeConnection();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,18 +65,17 @@ public class LiquibaseEndpoint {
|
||||
DatabaseFactory factory = DatabaseFactory.getInstance();
|
||||
StandardChangeLogHistoryService service = new StandardChangeLogHistoryService();
|
||||
this.context.getBeansOfType(SpringLiquibase.class)
|
||||
.forEach((name, liquibase) -> liquibaseBeans.put(name,
|
||||
createReport(liquibase, service, factory)));
|
||||
.forEach((name, liquibase) -> liquibaseBeans.put(name, createReport(liquibase, service, factory)));
|
||||
ApplicationContext parent = target.getParent();
|
||||
contextBeans.put(target.getId(), new ContextLiquibaseBeans(liquibaseBeans,
|
||||
(parent != null) ? parent.getId() : null));
|
||||
contextBeans.put(target.getId(),
|
||||
new ContextLiquibaseBeans(liquibaseBeans, (parent != null) ? parent.getId() : null));
|
||||
target = parent;
|
||||
}
|
||||
return new ApplicationLiquibaseBeans(contextBeans);
|
||||
}
|
||||
|
||||
private LiquibaseBean createReport(SpringLiquibase liquibase,
|
||||
ChangeLogHistoryService service, DatabaseFactory factory) {
|
||||
private LiquibaseBean createReport(SpringLiquibase liquibase, ChangeLogHistoryService service,
|
||||
DatabaseFactory factory) {
|
||||
try {
|
||||
DataSource dataSource = liquibase.getDataSource();
|
||||
JdbcConnection connection = new JdbcConnection(dataSource.getConnection());
|
||||
@@ -87,13 +86,11 @@ public class LiquibaseEndpoint {
|
||||
if (StringUtils.hasText(defaultSchema)) {
|
||||
database.setDefaultSchemaName(defaultSchema);
|
||||
}
|
||||
database.setDatabaseChangeLogTableName(
|
||||
liquibase.getDatabaseChangeLogTable());
|
||||
database.setDatabaseChangeLogLockTableName(
|
||||
liquibase.getDatabaseChangeLogLockTable());
|
||||
database.setDatabaseChangeLogTableName(liquibase.getDatabaseChangeLogTable());
|
||||
database.setDatabaseChangeLogLockTableName(liquibase.getDatabaseChangeLogLockTable());
|
||||
service.setDatabase(database);
|
||||
return new LiquibaseBean(service.getRanChangeSets().stream()
|
||||
.map(ChangeSet::new).collect(Collectors.toList()));
|
||||
return new LiquibaseBean(
|
||||
service.getRanChangeSets().stream().map(ChangeSet::new).collect(Collectors.toList()));
|
||||
}
|
||||
finally {
|
||||
if (database != null) {
|
||||
@@ -137,8 +134,7 @@ public class LiquibaseEndpoint {
|
||||
|
||||
private final String parentId;
|
||||
|
||||
private ContextLiquibaseBeans(Map<String, LiquibaseBean> liquibaseBeans,
|
||||
String parentId) {
|
||||
private ContextLiquibaseBeans(Map<String, LiquibaseBean> liquibaseBeans, String parentId) {
|
||||
this.liquibaseBeans = liquibaseBeans;
|
||||
this.parentId = parentId;
|
||||
}
|
||||
@@ -207,15 +203,14 @@ public class LiquibaseEndpoint {
|
||||
this.changeLog = ranChangeSet.getChangeLog();
|
||||
this.comments = ranChangeSet.getComments();
|
||||
this.contexts = ranChangeSet.getContextExpression().getContexts();
|
||||
this.dateExecuted = Instant
|
||||
.ofEpochMilli(ranChangeSet.getDateExecuted().getTime());
|
||||
this.dateExecuted = Instant.ofEpochMilli(ranChangeSet.getDateExecuted().getTime());
|
||||
this.deploymentId = ranChangeSet.getDeploymentId();
|
||||
this.description = ranChangeSet.getDescription();
|
||||
this.execType = ranChangeSet.getExecType();
|
||||
this.id = ranChangeSet.getId();
|
||||
this.labels = ranChangeSet.getLabels().getLabels();
|
||||
this.checksum = ((ranChangeSet.getLastCheckSum() != null)
|
||||
? ranChangeSet.getLastCheckSum().toString() : null);
|
||||
this.checksum = ((ranChangeSet.getLastCheckSum() != null) ? ranChangeSet.getLastCheckSum().toString()
|
||||
: null);
|
||||
this.orderExecuted = ranChangeSet.getOrderExecuted();
|
||||
this.tag = ranChangeSet.getTag();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -57,8 +57,7 @@ public class LoggersEndpoint {
|
||||
|
||||
@ReadOperation
|
||||
public Map<String, Object> loggers() {
|
||||
Collection<LoggerConfiguration> configurations = this.loggingSystem
|
||||
.getLoggerConfigurations();
|
||||
Collection<LoggerConfiguration> configurations = this.loggingSystem.getLoggerConfigurations();
|
||||
if (configurations == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
@@ -71,14 +70,12 @@ public class LoggersEndpoint {
|
||||
@ReadOperation
|
||||
public LoggerLevels loggerLevels(@Selector String name) {
|
||||
Assert.notNull(name, "Name must not be null");
|
||||
LoggerConfiguration configuration = this.loggingSystem
|
||||
.getLoggerConfiguration(name);
|
||||
LoggerConfiguration configuration = this.loggingSystem.getLoggerConfiguration(name);
|
||||
return (configuration != null) ? new LoggerLevels(configuration) : null;
|
||||
}
|
||||
|
||||
@WriteOperation
|
||||
public void configureLogLevel(@Selector String name,
|
||||
@Nullable LogLevel configuredLevel) {
|
||||
public void configureLogLevel(@Selector String name, @Nullable LogLevel configuredLevel) {
|
||||
Assert.notNull(name, "Name must not be empty");
|
||||
this.loggingSystem.setLogLevel(name, configuredLevel);
|
||||
}
|
||||
@@ -88,8 +85,7 @@ public class LoggersEndpoint {
|
||||
return new TreeSet<>(levels).descendingSet();
|
||||
}
|
||||
|
||||
private Map<String, LoggerLevels> getLoggers(
|
||||
Collection<LoggerConfiguration> configurations) {
|
||||
private Map<String, LoggerLevels> getLoggers(Collection<LoggerConfiguration> configurations) {
|
||||
Map<String, LoggerLevels> loggers = new LinkedHashMap<>(configurations.size());
|
||||
for (LoggerConfiguration configuration : configurations) {
|
||||
loggers.put(configuration.getName(), new LoggerLevels(configuration));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -38,8 +38,7 @@ public class MailHealthIndicator extends AbstractHealthIndicator {
|
||||
|
||||
@Override
|
||||
protected void doHealthCheck(Builder builder) throws Exception {
|
||||
builder.withDetail("location",
|
||||
this.mailSender.getHost() + ":" + this.mailSender.getPort());
|
||||
builder.withDetail("location", this.mailSender.getHost() + ":" + this.mailSender.getPort());
|
||||
this.mailSender.testConnection();
|
||||
builder.up();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -77,8 +77,7 @@ public class HeapDumpWebEndpoint {
|
||||
try {
|
||||
if (this.lock.tryLock(this.timeout, TimeUnit.MILLISECONDS)) {
|
||||
try {
|
||||
return new WebEndpointResponse<>(
|
||||
dumpHeap((live != null) ? live : true));
|
||||
return new WebEndpointResponse<>(dumpHeap((live != null) ? live : true));
|
||||
}
|
||||
finally {
|
||||
this.lock.unlock();
|
||||
@@ -89,12 +88,10 @@ public class HeapDumpWebEndpoint {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
return new WebEndpointResponse<>(
|
||||
WebEndpointResponse.STATUS_INTERNAL_SERVER_ERROR);
|
||||
return new WebEndpointResponse<>(WebEndpointResponse.STATUS_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
catch (HeapDumperUnavailableException ex) {
|
||||
return new WebEndpointResponse<>(
|
||||
WebEndpointResponse.STATUS_SERVICE_UNAVAILABLE);
|
||||
return new WebEndpointResponse<>(WebEndpointResponse.STATUS_SERVICE_UNAVAILABLE);
|
||||
}
|
||||
return new WebEndpointResponse<>(WebEndpointResponse.STATUS_TOO_MANY_REQUESTS);
|
||||
}
|
||||
@@ -110,8 +107,7 @@ public class HeapDumpWebEndpoint {
|
||||
|
||||
private File createTempFile(boolean live) throws IOException {
|
||||
String date = new SimpleDateFormat("yyyy-MM-dd-HH-mm").format(new Date());
|
||||
File file = File.createTempFile("heapdump" + date + (live ? "-live" : ""),
|
||||
".hprof");
|
||||
File file = File.createTempFile("heapdump" + date + (live ? "-live" : ""), ".hprof");
|
||||
file.delete();
|
||||
return file;
|
||||
}
|
||||
@@ -156,23 +152,21 @@ public class HeapDumpWebEndpoint {
|
||||
@SuppressWarnings("unchecked")
|
||||
protected HotSpotDiagnosticMXBeanHeapDumper() {
|
||||
try {
|
||||
Class<?> diagnosticMXBeanClass = ClassUtils.resolveClassName(
|
||||
"com.sun.management.HotSpotDiagnosticMXBean", null);
|
||||
this.diagnosticMXBean = ManagementFactory.getPlatformMXBean(
|
||||
(Class<PlatformManagedObject>) diagnosticMXBeanClass);
|
||||
this.dumpHeapMethod = ReflectionUtils.findMethod(diagnosticMXBeanClass,
|
||||
"dumpHeap", String.class, Boolean.TYPE);
|
||||
Class<?> diagnosticMXBeanClass = ClassUtils
|
||||
.resolveClassName("com.sun.management.HotSpotDiagnosticMXBean", null);
|
||||
this.diagnosticMXBean = ManagementFactory
|
||||
.getPlatformMXBean((Class<PlatformManagedObject>) diagnosticMXBeanClass);
|
||||
this.dumpHeapMethod = ReflectionUtils.findMethod(diagnosticMXBeanClass, "dumpHeap", String.class,
|
||||
Boolean.TYPE);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new HeapDumperUnavailableException(
|
||||
"Unable to locate HotSpotDiagnosticMXBean", ex);
|
||||
throw new HeapDumperUnavailableException("Unable to locate HotSpotDiagnosticMXBean", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dumpHeap(File file, boolean live) {
|
||||
ReflectionUtils.invokeMethod(this.dumpHeapMethod, this.diagnosticMXBean,
|
||||
file.getAbsolutePath(), live);
|
||||
ReflectionUtils.invokeMethod(this.dumpHeapMethod, this.diagnosticMXBean, file.getAbsolutePath(), live);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -245,9 +239,8 @@ public class HeapDumpWebEndpoint {
|
||||
Files.delete(getFile().toPath());
|
||||
}
|
||||
catch (IOException ex) {
|
||||
TemporaryFileSystemResource.this.logger.warn(
|
||||
"Failed to delete temporary heap dump file '" + getFile() + "'",
|
||||
ex);
|
||||
TemporaryFileSystemResource.this.logger
|
||||
.warn("Failed to delete temporary heap dump file '" + getFile() + "'", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -36,8 +36,7 @@ public class ThreadDumpEndpoint {
|
||||
|
||||
@ReadOperation
|
||||
public ThreadDumpDescriptor threadDump() {
|
||||
return new ThreadDumpDescriptor(Arrays
|
||||
.asList(ManagementFactory.getThreadMXBean().dumpAllThreads(true, true)));
|
||||
return new ThreadDumpDescriptor(Arrays.asList(ManagementFactory.getThreadMXBean().dumpAllThreads(true, true)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user