Polish endpoint
This commit is contained in:
parent
98455e30dc
commit
f9e5b07eec
|
|
@ -23,7 +23,7 @@ import java.lang.annotation.RetentionPolicy;
|
|||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.boot.endpoint.Endpoint;
|
||||
import org.springframework.boot.endpoint.EndpointType;
|
||||
import org.springframework.boot.endpoint.EndpointDelivery;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
|
||||
/**
|
||||
|
|
@ -33,8 +33,8 @@ import org.springframework.context.annotation.Conditional;
|
|||
* <p>
|
||||
* If no specific {@code endpoints.<id>.*} or {@code endpoints.default.*} properties are
|
||||
* defined, the condition matches the {@code enabledByDefault} value regardless of the
|
||||
* specific {@link EndpointType}, if any. If any property are set, they are evaluated with
|
||||
* a sensible order of precedence.
|
||||
* specific {@link EndpointDelivery}, if any. If any property are set, they are evaluated
|
||||
* with a sensible order of precedence.
|
||||
* <p>
|
||||
* For instance if {@code endpoints.default.enabled} is {@code false} but
|
||||
* {@code endpoints.<id>.enabled} is {@code true}, the condition will match.
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionMessage;
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.boot.endpoint.Endpoint;
|
||||
import org.springframework.boot.endpoint.EndpointType;
|
||||
import org.springframework.boot.endpoint.EndpointDelivery;
|
||||
import org.springframework.boot.endpoint.jmx.JmxEndpointExtension;
|
||||
import org.springframework.boot.endpoint.web.WebEndpointExtension;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
|
@ -30,6 +30,7 @@ import org.springframework.context.annotation.ConditionContext;
|
|||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.core.type.MethodMetadata;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
|
@ -44,14 +45,9 @@ class OnEnabledEndpointCondition extends SpringBootCondition {
|
|||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
EndpointAttributes endpoint = getEndpointAttributes(context, metadata);
|
||||
if (!StringUtils.hasText(endpoint.id)) {
|
||||
throw new IllegalStateException("Endpoint id could not be determined");
|
||||
}
|
||||
EndpointEnablementProvider enablementProvider = new EndpointEnablementProvider(
|
||||
context.getEnvironment());
|
||||
EndpointEnablement endpointEnablement = enablementProvider.getEndpointEnablement(
|
||||
endpoint.id, endpoint.enabled, endpoint.endpointType);
|
||||
EndpointAttributes attributes = getEndpointAttributes(context, metadata);
|
||||
EndpointEnablement endpointEnablement = attributes
|
||||
.getEnablement(new EndpointEnablementProvider(context.getEnvironment()));
|
||||
return new ConditionOutcome(endpointEnablement.isEnabled(),
|
||||
ConditionMessage.forCondition(ConditionalOnEnabledEndpoint.class)
|
||||
.because(endpointEnablement.getReason()));
|
||||
|
|
@ -59,24 +55,27 @@ class OnEnabledEndpointCondition extends SpringBootCondition {
|
|||
|
||||
private EndpointAttributes getEndpointAttributes(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
if (metadata instanceof MethodMetadata
|
||||
&& metadata.isAnnotated(Bean.class.getName())) {
|
||||
MethodMetadata methodMetadata = (MethodMetadata) metadata;
|
||||
try {
|
||||
// We should be safe to load at this point since we are in the
|
||||
// REGISTER_BEAN phase
|
||||
Class<?> returnType = ClassUtils.forName(
|
||||
methodMetadata.getReturnTypeName(), context.getClassLoader());
|
||||
return extractEndpointAttributes(returnType);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalStateException("Failed to extract endpoint id for "
|
||||
+ methodMetadata.getDeclaringClassName() + "."
|
||||
+ methodMetadata.getMethodName(), ex);
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException(
|
||||
Assert.state(
|
||||
metadata instanceof MethodMetadata
|
||||
&& metadata.isAnnotated(Bean.class.getName()),
|
||||
"OnEnabledEndpointCondition may only be used on @Bean methods");
|
||||
return getEndpointAttributes(context, (MethodMetadata) metadata);
|
||||
}
|
||||
|
||||
private EndpointAttributes getEndpointAttributes(ConditionContext context,
|
||||
MethodMetadata methodMetadata) {
|
||||
try {
|
||||
// We should be safe to load at this point since we are in the
|
||||
// REGISTER_BEAN phase
|
||||
Class<?> returnType = ClassUtils.forName(methodMetadata.getReturnTypeName(),
|
||||
context.getClassLoader());
|
||||
return extractEndpointAttributes(returnType);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalStateException("Failed to extract endpoint id for "
|
||||
+ methodMetadata.getDeclaringClassName() + "."
|
||||
+ methodMetadata.getMethodName(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected EndpointAttributes extractEndpointAttributes(Class<?> type) {
|
||||
|
|
@ -105,11 +104,10 @@ class OnEnabledEndpointCondition extends SpringBootCondition {
|
|||
if (endpoint == null) {
|
||||
return null;
|
||||
}
|
||||
// If both types are set, all techs are exposed
|
||||
EndpointType endpointType = (endpoint.types().length == 1 ? endpoint.types()[0]
|
||||
: null);
|
||||
// If both types are set, all delivery technologies are exposed
|
||||
EndpointDelivery[] delivery = endpoint.delivery();
|
||||
return new EndpointAttributes(endpoint.id(), endpoint.enabledByDefault(),
|
||||
endpointType);
|
||||
(delivery.length == 1 ? delivery[0] : null));
|
||||
}
|
||||
|
||||
private static class EndpointAttributes {
|
||||
|
|
@ -118,12 +116,19 @@ class OnEnabledEndpointCondition extends SpringBootCondition {
|
|||
|
||||
private final boolean enabled;
|
||||
|
||||
private final EndpointType endpointType;
|
||||
private final EndpointDelivery delivery;
|
||||
|
||||
EndpointAttributes(String id, boolean enabled, EndpointType endpointType) {
|
||||
EndpointAttributes(String id, boolean enabled, EndpointDelivery delivery) {
|
||||
if (!StringUtils.hasText(id)) {
|
||||
throw new IllegalStateException("Endpoint id could not be determined");
|
||||
}
|
||||
this.id = id;
|
||||
this.enabled = enabled;
|
||||
this.endpointType = endpointType;
|
||||
this.delivery = delivery;
|
||||
}
|
||||
|
||||
public EndpointEnablement getEnablement(EndpointEnablementProvider provider) {
|
||||
return provider.getEndpointEnablement(this.id, this.enabled, this.delivery);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat
|
|||
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.endpoint.ConversionServiceOperationParameterMapper;
|
||||
import org.springframework.boot.endpoint.EndpointType;
|
||||
import org.springframework.boot.endpoint.EndpointDelivery;
|
||||
import org.springframework.boot.endpoint.OperationParameterMapper;
|
||||
import org.springframework.boot.endpoint.jmx.EndpointMBeanRegistrar;
|
||||
import org.springframework.boot.endpoint.jmx.JmxAnnotationEndpointDiscoverer;
|
||||
|
|
@ -102,10 +102,10 @@ public class EndpointInfrastructureAutoConfiguration {
|
|||
ObjectProvider<ObjectMapper> objectMapper) {
|
||||
EndpointProvider<JmxEndpointOperation> endpointProvider = new EndpointProvider<>(
|
||||
this.applicationContext.getEnvironment(), endpointDiscoverer,
|
||||
EndpointType.JMX);
|
||||
EndpointDelivery.JMX);
|
||||
EndpointMBeanRegistrar endpointMBeanRegistrar = new EndpointMBeanRegistrar(
|
||||
mBeanServer, new DefaultEndpointObjectNameFactory(properties,
|
||||
mBeanServer, ObjectUtils.getIdentityHexString(this.applicationContext)));
|
||||
mBeanServer, new DefaultEndpointObjectNameFactory(properties, mBeanServer,
|
||||
ObjectUtils.getIdentityHexString(this.applicationContext)));
|
||||
return new JmxEndpointExporter(endpointProvider, endpointMBeanRegistrar,
|
||||
objectMapper.getIfAvailable(ObjectMapper::new));
|
||||
}
|
||||
|
|
@ -127,7 +127,7 @@ public class EndpointInfrastructureAutoConfiguration {
|
|||
return new EndpointProvider<>(this.applicationContext.getEnvironment(),
|
||||
webEndpointDiscoverer(operationParameterMapper,
|
||||
cachingConfigurationFactory),
|
||||
EndpointType.WEB);
|
||||
EndpointDelivery.WEB);
|
||||
}
|
||||
|
||||
private WebAnnotationEndpointDiscoverer webEndpointDiscoverer(
|
||||
|
|
|
|||
|
|
@ -20,10 +20,10 @@ import java.util.Collection;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.endpoint.support.EndpointEnablementProvider;
|
||||
import org.springframework.boot.endpoint.EndpointDelivery;
|
||||
import org.springframework.boot.endpoint.EndpointDiscoverer;
|
||||
import org.springframework.boot.endpoint.EndpointInfo;
|
||||
import org.springframework.boot.endpoint.EndpointOperation;
|
||||
import org.springframework.boot.endpoint.EndpointType;
|
||||
import org.springframework.boot.endpoint.Operation;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
/**
|
||||
|
|
@ -34,25 +34,25 @@ import org.springframework.core.env.Environment;
|
|||
* @author Stephane Nicoll
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public final class EndpointProvider<T extends EndpointOperation> {
|
||||
public final class EndpointProvider<T extends Operation> {
|
||||
|
||||
private final EndpointDiscoverer<T> discoverer;
|
||||
|
||||
private final EndpointEnablementProvider endpointEnablementProvider;
|
||||
|
||||
private final EndpointType endpointType;
|
||||
private final EndpointDelivery delivery;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param environment the environment to use to check the endpoints that are enabled
|
||||
* @param discoverer the discoverer to get the initial set of endpoints
|
||||
* @param endpointType the type of endpoint to handle
|
||||
* @param delivery the delivery technology for the endpoint
|
||||
*/
|
||||
public EndpointProvider(Environment environment, EndpointDiscoverer<T> discoverer,
|
||||
EndpointType endpointType) {
|
||||
EndpointDelivery delivery) {
|
||||
this.discoverer = discoverer;
|
||||
this.endpointEnablementProvider = new EndpointEnablementProvider(environment);
|
||||
this.endpointType = endpointType;
|
||||
this.delivery = delivery;
|
||||
}
|
||||
|
||||
public Collection<EndpointInfo<T>> getEndpoints() {
|
||||
|
|
@ -62,7 +62,7 @@ public final class EndpointProvider<T extends EndpointOperation> {
|
|||
|
||||
private boolean isEnabled(EndpointInfo<?> endpoint) {
|
||||
return this.endpointEnablementProvider.getEndpointEnablement(endpoint.getId(),
|
||||
endpoint.isEnabledByDefault(), this.endpointType).isEnabled();
|
||||
endpoint.isEnabledByDefault(), this.delivery).isEnabled();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.support;
|
|||
public final class EndpointEnablement {
|
||||
|
||||
private final boolean enabled;
|
||||
|
||||
private final String reason;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@
|
|||
|
||||
package org.springframework.boot.actuate.autoconfigure.endpoint.support;
|
||||
|
||||
import org.springframework.boot.endpoint.EndpointType;
|
||||
import org.springframework.boot.endpoint.EndpointDelivery;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Determines an endpoint's enablement based on the current {@link Environment}.
|
||||
|
|
@ -54,109 +54,111 @@ public class EndpointEnablementProvider {
|
|||
* Return the {@link EndpointEnablement} of an endpoint for a specific tech exposure.
|
||||
* @param endpointId the id of the endpoint
|
||||
* @param enabledByDefault whether the endpoint is enabled by default or not
|
||||
* @param endpointType the requested {@link EndpointType}
|
||||
* @param delivery the requested {@link EndpointDelivery}
|
||||
* @return the {@link EndpointEnablement} of that endpoint for the specified
|
||||
* {@link EndpointType}
|
||||
* {@link EndpointDelivery}
|
||||
*/
|
||||
public EndpointEnablement getEndpointEnablement(String endpointId,
|
||||
boolean enabledByDefault, EndpointType endpointType) {
|
||||
if (!StringUtils.hasText(endpointId)) {
|
||||
throw new IllegalArgumentException("Endpoint id must have a value");
|
||||
boolean enabledByDefault, EndpointDelivery delivery) {
|
||||
Assert.hasText(endpointId, "Endpoint id must have a value");
|
||||
Assert.isTrue(!endpointId.equals("default"), "Endpoint id 'default' is a reserved "
|
||||
+ "value and cannot be used by an endpoint");
|
||||
EndpointEnablement result = findEnablement(endpointId, delivery);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
if (endpointId.equals("default")) {
|
||||
throw new IllegalArgumentException("Endpoint id 'default' is a reserved "
|
||||
+ "value and cannot be used by an endpoint");
|
||||
result = findEnablement(getKey(endpointId, "enabled"));
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (endpointType != null) {
|
||||
String endpointTypeKey = createTechSpecificKey(endpointId, endpointType);
|
||||
EndpointEnablement endpointTypeSpecificOutcome = getEnablementFor(
|
||||
endpointTypeKey);
|
||||
if (endpointTypeSpecificOutcome != null) {
|
||||
return endpointTypeSpecificOutcome;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If any tech specific is on at this point we should enable the endpoint
|
||||
EndpointEnablement anyTechSpecificOutcome = getAnyTechSpecificOutcomeFor(
|
||||
endpointId);
|
||||
if (anyTechSpecificOutcome != null) {
|
||||
return anyTechSpecificOutcome;
|
||||
}
|
||||
}
|
||||
String endpointKey = createKey(endpointId, "enabled");
|
||||
EndpointEnablement endpointSpecificOutcome = getEnablementFor(endpointKey);
|
||||
if (endpointSpecificOutcome != null) {
|
||||
return endpointSpecificOutcome;
|
||||
}
|
||||
|
||||
// All endpoints specific attributes have been looked at. Checking default value
|
||||
// for the endpoint
|
||||
if (!enabledByDefault) {
|
||||
return defaultEndpointEnablement(endpointId, false, endpointType);
|
||||
return getDefaultEndpointEnablement(endpointId, false, delivery);
|
||||
}
|
||||
|
||||
if (endpointType != null) {
|
||||
String defaultTypeKey = createTechSpecificKey("default", endpointType);
|
||||
EndpointEnablement globalTypeOutcome = getEnablementFor(defaultTypeKey);
|
||||
if (globalTypeOutcome != null) {
|
||||
return globalTypeOutcome;
|
||||
}
|
||||
if (!endpointType.isEnabledByDefault()) {
|
||||
return defaultEndpointEnablement("default", false, endpointType);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Check if there is a global tech required
|
||||
EndpointEnablement anyTechGeneralOutcome = getAnyTechSpecificOutcomeFor(
|
||||
"default");
|
||||
if (anyTechGeneralOutcome != null) {
|
||||
return anyTechGeneralOutcome;
|
||||
}
|
||||
}
|
||||
|
||||
String defaultKey = createKey("default", "enabled");
|
||||
EndpointEnablement globalOutCome = getEnablementFor(defaultKey);
|
||||
if (globalOutCome != null) {
|
||||
return globalOutCome;
|
||||
}
|
||||
return defaultEndpointEnablement(endpointId, enabledByDefault, endpointType);
|
||||
return getGlobalEndpointEnablement(endpointId, enabledByDefault,
|
||||
delivery);
|
||||
}
|
||||
|
||||
private EndpointEnablement defaultEndpointEnablement(String endpointId,
|
||||
boolean enabledByDefault, EndpointType endpointType) {
|
||||
return new EndpointEnablement(enabledByDefault, createDefaultEnablementMessage(
|
||||
endpointId, enabledByDefault, endpointType));
|
||||
}
|
||||
|
||||
private String createDefaultEnablementMessage(String endpointId,
|
||||
boolean enabledByDefault, EndpointType endpointType) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(String.format("endpoint '%s' ", endpointId));
|
||||
if (endpointType != null) {
|
||||
sb.append(String.format("(%s) ", endpointType.name().toLowerCase()));
|
||||
private EndpointEnablement findEnablement(String endpointId,
|
||||
EndpointDelivery delivery) {
|
||||
if (delivery != null) {
|
||||
return findEnablement(getKey(endpointId, delivery));
|
||||
}
|
||||
sb.append(String.format("is %s by default",
|
||||
(enabledByDefault ? "enabled" : "disabled")));
|
||||
return sb.toString();
|
||||
return findEnablementForAnyDeliveryTechnology(endpointId);
|
||||
}
|
||||
|
||||
private EndpointEnablement getAnyTechSpecificOutcomeFor(String endpointId) {
|
||||
for (EndpointType endpointType : EndpointType.values()) {
|
||||
String key = createTechSpecificKey(endpointId, endpointType);
|
||||
EndpointEnablement outcome = getEnablementFor(key);
|
||||
if (outcome != null && outcome.isEnabled()) {
|
||||
return outcome;
|
||||
private EndpointEnablement getGlobalEndpointEnablement(String endpointId,
|
||||
boolean enabledByDefault, EndpointDelivery delivery) {
|
||||
EndpointEnablement result = findGlobalEndpointEnablement(delivery);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
result = findEnablement(getKey("default", "enabled"));
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
return getDefaultEndpointEnablement(endpointId, enabledByDefault,
|
||||
delivery);
|
||||
}
|
||||
|
||||
private EndpointEnablement findGlobalEndpointEnablement(
|
||||
EndpointDelivery delivery) {
|
||||
if (delivery != null) {
|
||||
EndpointEnablement result = findEnablement(getKey("default", delivery));
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
if (!delivery.isEnabledByDefault()) {
|
||||
return getDefaultEndpointEnablement("default", false, delivery);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return findEnablementForAnyDeliveryTechnology("default");
|
||||
}
|
||||
|
||||
private EndpointEnablement findEnablementForAnyDeliveryTechnology(String endpointId) {
|
||||
for (EndpointDelivery candidate : EndpointDelivery.values()) {
|
||||
EndpointEnablement result = findEnablementForDeliveryTechnology(endpointId,
|
||||
candidate);
|
||||
if (result != null && result.isEnabled()) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String createTechSpecificKey(String endpointId, EndpointType endpointType) {
|
||||
return createKey(endpointId, endpointType.name().toLowerCase() + ".enabled");
|
||||
private EndpointEnablement findEnablementForDeliveryTechnology(String endpointId,
|
||||
EndpointDelivery delivery) {
|
||||
String endpointTypeKey = getKey(endpointId, delivery);
|
||||
EndpointEnablement endpointTypeSpecificOutcome = findEnablement(endpointTypeKey);
|
||||
return endpointTypeSpecificOutcome;
|
||||
}
|
||||
|
||||
private String createKey(String endpointId, String suffix) {
|
||||
private EndpointEnablement getDefaultEndpointEnablement(String endpointId,
|
||||
boolean enabledByDefault, EndpointDelivery delivery) {
|
||||
return new EndpointEnablement(enabledByDefault, createDefaultEnablementMessage(
|
||||
endpointId, enabledByDefault, delivery));
|
||||
}
|
||||
|
||||
private String createDefaultEnablementMessage(String endpointId,
|
||||
boolean enabledByDefault, EndpointDelivery delivery) {
|
||||
StringBuilder message = new StringBuilder();
|
||||
message.append(String.format("endpoint '%s' ", endpointId));
|
||||
if (delivery != null) {
|
||||
message.append(
|
||||
String.format("(%s) ", delivery.name().toLowerCase()));
|
||||
}
|
||||
message.append(String.format("is %s by default",
|
||||
(enabledByDefault ? "enabled" : "disabled")));
|
||||
return message.toString();
|
||||
}
|
||||
|
||||
private String getKey(String endpointId, EndpointDelivery delivery) {
|
||||
return getKey(endpointId, delivery.name().toLowerCase() + ".enabled");
|
||||
}
|
||||
|
||||
private String getKey(String endpointId, String suffix) {
|
||||
return "endpoints." + endpointId + "." + suffix;
|
||||
}
|
||||
|
||||
|
|
@ -166,7 +168,7 @@ public class EndpointEnablementProvider {
|
|||
* @param key the key to check
|
||||
* @return the outcome or {@code null} if the key is no set
|
||||
*/
|
||||
private EndpointEnablement getEnablementFor(String key) {
|
||||
private EndpointEnablement findEnablement(String key) {
|
||||
if (this.environment.containsProperty(key)) {
|
||||
boolean match = this.environment.getProperty(key, Boolean.class, true);
|
||||
return new EndpointEnablement(match, String.format("found property %s", key));
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe
|
|||
@Override
|
||||
protected void registerMappingForOperation(WebEndpointOperation operation) {
|
||||
registerMapping(createRequestMappingInfo(operation),
|
||||
new OperationHandler(operation.getOperationInvoker(), operation.getId(), this.securityInterceptor), this.handle);
|
||||
new OperationHandler(operation.getInvoker(), operation.getId(), this.securityInterceptor), this.handle);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ import org.apache.commons.logging.LogFactory;
|
|||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.endpoint.Endpoint;
|
||||
import org.springframework.boot.endpoint.EndpointType;
|
||||
import org.springframework.boot.endpoint.EndpointDelivery;
|
||||
import org.springframework.boot.endpoint.ReadOperation;
|
||||
import org.springframework.boot.endpoint.web.WebEndpointResponse;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
|
|
@ -55,7 +55,7 @@ import org.springframework.util.ReflectionUtils;
|
|||
* @since 2.0.0
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "endpoints.heapdump")
|
||||
@Endpoint(id = "heapdump", types = EndpointType.WEB)
|
||||
@Endpoint(id = "heapdump", delivery = EndpointDelivery.WEB)
|
||||
public class HeapDumpWebEndpoint {
|
||||
|
||||
private final long timeout;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import org.apache.commons.logging.LogFactory;
|
|||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.endpoint.Endpoint;
|
||||
import org.springframework.boot.endpoint.EndpointType;
|
||||
import org.springframework.boot.endpoint.EndpointDelivery;
|
||||
import org.springframework.boot.endpoint.ReadOperation;
|
||||
import org.springframework.boot.logging.LogFile;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
|
@ -39,7 +39,7 @@ import org.springframework.core.io.Resource;
|
|||
* @since 2.0.0
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "endpoints.logfile")
|
||||
@Endpoint(id = "logfile", types = EndpointType.WEB)
|
||||
@Endpoint(id = "logfile", delivery = EndpointDelivery.WEB)
|
||||
public class LogFileWebEndpoint {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(LogFileWebEndpoint.class);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ package org.springframework.boot.actuate.autoconfigure.endpoint;
|
|||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.endpoint.Endpoint;
|
||||
import org.springframework.boot.endpoint.EndpointType;
|
||||
import org.springframework.boot.endpoint.EndpointDelivery;
|
||||
import org.springframework.boot.endpoint.jmx.JmxEndpointExtension;
|
||||
import org.springframework.boot.endpoint.web.WebEndpointExtension;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
|
|
@ -297,8 +297,8 @@ public class ConditionalOnEnabledEndpointTests {
|
|||
|
||||
}
|
||||
|
||||
@Endpoint(id = "bar", types = { EndpointType.WEB,
|
||||
EndpointType.JMX }, enabledByDefault = false)
|
||||
@Endpoint(id = "bar", delivery = { EndpointDelivery.WEB,
|
||||
EndpointDelivery.JMX }, enabledByDefault = false)
|
||||
static class BarEndpoint {
|
||||
|
||||
}
|
||||
|
|
@ -314,7 +314,7 @@ public class ConditionalOnEnabledEndpointTests {
|
|||
|
||||
}
|
||||
|
||||
@Endpoint(id = "onlyweb", types = EndpointType.WEB)
|
||||
@Endpoint(id = "onlyweb", delivery = EndpointDelivery.WEB)
|
||||
static class OnlyWebEndpoint {
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import org.junit.Rule;
|
|||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.boot.endpoint.EndpointType;
|
||||
import org.springframework.boot.endpoint.EndpointDelivery;
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
|
@ -41,7 +41,7 @@ public class EndpointEnablementProviderTests {
|
|||
public void cannotDetermineEnablementWithEmptyEndpoint() {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Endpoint id must have a value");
|
||||
determineEnablement(" ", true);
|
||||
getEndpointEnablement(" ", true);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -49,289 +49,295 @@ public class EndpointEnablementProviderTests {
|
|||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Endpoint id 'default' is a reserved value and cannot "
|
||||
+ "be used by an endpoint");
|
||||
determineEnablement("default", true);
|
||||
getEndpointEnablement("default", true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalEnabledByDefault() {
|
||||
validate(determineEnablement("foo", true), true,
|
||||
"endpoint 'foo' is enabled by default");
|
||||
EndpointEnablement enablement = getEndpointEnablement("foo", true);
|
||||
validate(enablement, true, "endpoint 'foo' is enabled by default");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalDisabledViaSpecificProperty() {
|
||||
validate(determineEnablement("foo", true, "endpoints.foo.enabled=false"), false,
|
||||
"found property endpoints.foo.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("foo", true,
|
||||
"endpoints.foo.enabled=false");
|
||||
validate(enablement, false, "found property endpoints.foo.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalDisabledViaGeneralProperty() {
|
||||
validate(determineEnablement("foo", true, "endpoints.default.enabled=false"), false,
|
||||
"found property endpoints.default.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("foo", true,
|
||||
"endpoints.default.enabled=false");
|
||||
validate(enablement, false, "found property endpoints.default.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalEnabledOverrideViaSpecificProperty() {
|
||||
validate(
|
||||
determineEnablement("foo", true, "endpoints.default.enabled=false",
|
||||
"endpoints.foo.enabled=true"),
|
||||
true, "found property endpoints.foo.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("foo", true,
|
||||
"endpoints.default.enabled=false", "endpoints.foo.enabled=true");
|
||||
validate(enablement, true, "found property endpoints.foo.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalEnabledOverrideViaSpecificWebProperty() {
|
||||
validate(
|
||||
determineEnablement("foo", true, "endpoints.foo.enabled=false",
|
||||
"endpoints.foo.web.enabled=true"),
|
||||
true, "found property endpoints.foo.web.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("foo", true,
|
||||
"endpoints.foo.enabled=false", "endpoints.foo.web.enabled=true");
|
||||
validate(enablement, true, "found property endpoints.foo.web.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalEnabledOverrideViaSpecificJmxProperty() {
|
||||
validate(
|
||||
determineEnablement("foo", true, "endpoints.foo.enabled=false",
|
||||
"endpoints.foo.jmx.enabled=true"),
|
||||
true, "found property endpoints.foo.jmx.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("foo", true,
|
||||
"endpoints.foo.enabled=false", "endpoints.foo.jmx.enabled=true");
|
||||
validate(enablement, true, "found property endpoints.foo.jmx.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalEnabledOverrideViaSpecificAnyProperty() {
|
||||
validate(determineEnablement("foo", true, "endpoints.foo.enabled=false",
|
||||
validate(getEndpointEnablement("foo", true, "endpoints.foo.enabled=false",
|
||||
"endpoints.foo.web.enabled=false", "endpoints.foo.jmx.enabled=true"),
|
||||
true, "found property endpoints.foo.jmx.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalEnabledOverrideViaGeneralWebProperty() {
|
||||
validate(
|
||||
determineEnablement("foo", true, "endpoints.default.enabled=false",
|
||||
"endpoints.default.web.enabled=true"),
|
||||
true, "found property endpoints.default.web.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("foo", true,
|
||||
"endpoints.default.enabled=false", "endpoints.default.web.enabled=true");
|
||||
validate(enablement, true, "found property endpoints.default.web.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalEnabledOverrideViaGeneralJmxProperty() {
|
||||
validate(
|
||||
determineEnablement("foo", true, "endpoints.default.enabled=false",
|
||||
"endpoints.default.jmx.enabled=true"),
|
||||
true, "found property endpoints.default.jmx.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("foo", true,
|
||||
"endpoints.default.enabled=false", "endpoints.default.jmx.enabled=true");
|
||||
validate(enablement, true, "found property endpoints.default.jmx.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalEnabledOverrideViaGeneralAnyProperty() {
|
||||
validate(determineEnablement("foo", true, "endpoints.default.enabled=false",
|
||||
"endpoints.default.web.enabled=false", "endpoints.default.jmx.enabled=true"),
|
||||
true, "found property endpoints.default.jmx.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("foo", true,
|
||||
"endpoints.default.enabled=false", "endpoints.default.web.enabled=false",
|
||||
"endpoints.default.jmx.enabled=true");
|
||||
validate(enablement, true, "found property endpoints.default.jmx.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalDisabledEvenWithEnabledGeneralProperties() {
|
||||
validate(
|
||||
determineEnablement("foo", true, "endpoints.default.enabled=true",
|
||||
"endpoints.default.web.enabled=true",
|
||||
"endpoints.default.jmx.enabled=true", "endpoints.foo.enabled=false"),
|
||||
false, "found property endpoints.foo.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("foo", true,
|
||||
"endpoints.default.enabled=true", "endpoints.default.web.enabled=true",
|
||||
"endpoints.default.jmx.enabled=true", "endpoints.foo.enabled=false");
|
||||
validate(enablement, false, "found property endpoints.foo.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalDisabledByDefaultWithAnnotationFlag() {
|
||||
validate(determineEnablement("bar", false), false,
|
||||
"endpoint 'bar' is disabled by default");
|
||||
EndpointEnablement enablement = getEndpointEnablement("bar", false);
|
||||
validate(enablement, false, "endpoint 'bar' is disabled by default");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalDisabledByDefaultWithAnnotationFlagEvenWithGeneralProperty() {
|
||||
validate(determineEnablement("bar", false, "endpoints.default.enabled=true"), false,
|
||||
"endpoint 'bar' is disabled by default");
|
||||
EndpointEnablement enablement = getEndpointEnablement("bar", false,
|
||||
"endpoints.default.enabled=true");
|
||||
validate(enablement, false, "endpoint 'bar' is disabled by default");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalDisabledByDefaultWithAnnotationFlagEvenWithGeneralWebProperty() {
|
||||
validate(determineEnablement("bar", false, "endpoints.default.web.enabled=true"),
|
||||
false, "endpoint 'bar' is disabled by default");
|
||||
EndpointEnablement enablement = getEndpointEnablement("bar", false,
|
||||
"endpoints.default.web.enabled=true");
|
||||
validate(enablement, false, "endpoint 'bar' is disabled by default");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalDisabledByDefaultWithAnnotationFlagEvenWithGeneralJmxProperty() {
|
||||
validate(determineEnablement("bar", false, "endpoints.default.jmx.enabled=true"),
|
||||
false, "endpoint 'bar' is disabled by default");
|
||||
EndpointEnablement enablement = getEndpointEnablement("bar", false,
|
||||
"endpoints.default.jmx.enabled=true");
|
||||
validate(enablement, false, "endpoint 'bar' is disabled by default");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalEnabledOverrideWithAndAnnotationFlagAndSpecificProperty() {
|
||||
validate(determineEnablement("bar", false, "endpoints.bar.enabled=true"), true,
|
||||
"found property endpoints.bar.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("bar", false,
|
||||
"endpoints.bar.enabled=true");
|
||||
validate(enablement, true, "found property endpoints.bar.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalEnabledOverrideWithAndAnnotationFlagAndSpecificWebProperty() {
|
||||
validate(determineEnablement("bar", false, "endpoints.bar.web.enabled=true"),
|
||||
true, "found property endpoints.bar.web.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("bar", false,
|
||||
"endpoints.bar.web.enabled=true");
|
||||
validate(enablement, true, "found property endpoints.bar.web.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalEnabledOverrideWithAndAnnotationFlagAndSpecificJmxProperty() {
|
||||
validate(determineEnablement("bar", false, "endpoints.bar.jmx.enabled=true"),
|
||||
true, "found property endpoints.bar.jmx.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("bar", false,
|
||||
"endpoints.bar.jmx.enabled=true");
|
||||
validate(enablement, true, "found property endpoints.bar.jmx.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalEnabledOverrideWithAndAnnotationFlagAndAnyProperty() {
|
||||
validate(
|
||||
determineEnablement("bar", false, "endpoints.bar.web.enabled=false",
|
||||
"endpoints.bar.jmx.enabled=true"),
|
||||
true, "found property endpoints.bar.jmx.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("bar", false,
|
||||
"endpoints.bar.web.enabled=false", "endpoints.bar.jmx.enabled=true");
|
||||
validate(enablement, true, "found property endpoints.bar.jmx.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificEnabledByDefault() {
|
||||
validate(determineEnablement("foo", true, EndpointType.JMX), true,
|
||||
"endpoint 'foo' (jmx) is enabled by default");
|
||||
EndpointEnablement enablement = getEndpointEnablement("foo", true,
|
||||
EndpointDelivery.JMX);
|
||||
validate(enablement, true, "endpoint 'foo' (jmx) is enabled by default");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificDisabledViaEndpointProperty() {
|
||||
validate(
|
||||
determineEnablement("foo", true, EndpointType.WEB,
|
||||
"endpoints.foo.enabled=false"),
|
||||
false, "found property endpoints.foo.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("foo", true,
|
||||
EndpointDelivery.WEB, "endpoints.foo.enabled=false");
|
||||
validate(enablement, false, "found property endpoints.foo.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificDisabledViaTechProperty() {
|
||||
validate(
|
||||
determineEnablement("foo", true, EndpointType.WEB,
|
||||
"endpoints.foo.web.enabled=false"),
|
||||
false, "found property endpoints.foo.web.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("foo", true,
|
||||
EndpointDelivery.WEB, "endpoints.foo.web.enabled=false");
|
||||
validate(enablement, false, "found property endpoints.foo.web.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificNotDisabledViaUnrelatedTechProperty() {
|
||||
validate(
|
||||
determineEnablement("foo", true, EndpointType.JMX,
|
||||
"endpoints.foo.web.enabled=false"),
|
||||
true, "endpoint 'foo' (jmx) is enabled by default");
|
||||
EndpointEnablement enablement = getEndpointEnablement("foo", true,
|
||||
EndpointDelivery.JMX, "endpoints.foo.web.enabled=false");
|
||||
validate(enablement, true, "endpoint 'foo' (jmx) is enabled by default");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificDisabledViaGeneralProperty() {
|
||||
validate(
|
||||
determineEnablement("foo", true, EndpointType.JMX,
|
||||
"endpoints.default.enabled=false"),
|
||||
false, "found property endpoints.default.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("foo", true,
|
||||
EndpointDelivery.JMX, "endpoints.default.enabled=false");
|
||||
validate(enablement, false, "found property endpoints.default.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificEnabledOverrideViaEndpointProperty() {
|
||||
validate(
|
||||
determineEnablement("foo", true, EndpointType.WEB,
|
||||
"endpoints.default.enabled=false", "endpoints.foo.enabled=true"),
|
||||
true, "found property endpoints.foo.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("foo", true,
|
||||
EndpointDelivery.WEB, "endpoints.default.enabled=false",
|
||||
"endpoints.foo.enabled=true");
|
||||
validate(enablement, true, "found property endpoints.foo.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificEnabledOverrideViaTechProperty() {
|
||||
validate(
|
||||
determineEnablement("foo", true, EndpointType.WEB,
|
||||
"endpoints.foo.enabled=false", "endpoints.foo.web.enabled=true"),
|
||||
true, "found property endpoints.foo.web.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("foo", true,
|
||||
EndpointDelivery.WEB, "endpoints.foo.enabled=false",
|
||||
"endpoints.foo.web.enabled=true");
|
||||
validate(enablement, true, "found property endpoints.foo.web.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificEnabledOverrideHasNotEffectWithUnrelatedTechProperty() {
|
||||
validate(
|
||||
determineEnablement("foo", true, EndpointType.WEB,
|
||||
"endpoints.foo.enabled=false", "endpoints.foo.jmx.enabled=true"),
|
||||
false, "found property endpoints.foo.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("foo", true,
|
||||
EndpointDelivery.WEB, "endpoints.foo.enabled=false",
|
||||
"endpoints.foo.jmx.enabled=true");
|
||||
validate(enablement, false, "found property endpoints.foo.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificEnabledOverrideViaGeneralWebProperty() {
|
||||
validate(
|
||||
determineEnablement("foo", true, EndpointType.WEB,
|
||||
"endpoints.default.enabled=false", "endpoints.default.web.enabled=true"),
|
||||
true, "found property endpoints.default.web.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("foo", true,
|
||||
EndpointDelivery.WEB, "endpoints.default.enabled=false",
|
||||
"endpoints.default.web.enabled=true");
|
||||
validate(enablement, true, "found property endpoints.default.web.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificEnabledOverrideHasNoEffectWithUnrelatedTechProperty() {
|
||||
validate(
|
||||
determineEnablement("foo", true, EndpointType.JMX,
|
||||
getEndpointEnablement("foo", true, EndpointDelivery.JMX,
|
||||
"endpoints.default.enabled=false", "endpoints.default.web.enabled=true"),
|
||||
false, "found property endpoints.default.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificDisabledWithEndpointPropertyEvenWithEnabledGeneralProperties() {
|
||||
validate(
|
||||
determineEnablement("foo", true, EndpointType.WEB,
|
||||
"endpoints.default.enabled=true", "endpoints.default.web.enabled=true",
|
||||
"endpoints.default.jmx.enabled=true", "endpoints.foo.enabled=false"),
|
||||
false, "found property endpoints.foo.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("foo", true,
|
||||
EndpointDelivery.WEB, "endpoints.default.enabled=true",
|
||||
"endpoints.default.web.enabled=true", "endpoints.default.jmx.enabled=true",
|
||||
"endpoints.foo.enabled=false");
|
||||
validate(enablement, false, "found property endpoints.foo.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificDisabledWithTechPropertyEvenWithEnabledGeneralProperties() {
|
||||
validate(
|
||||
determineEnablement("foo", true, EndpointType.WEB,
|
||||
"endpoints.default.enabled=true", "endpoints.default.web.enabled=true",
|
||||
"endpoints.default.jmx.enabled=true", "endpoints.foo.enabled=true",
|
||||
"endpoints.foo.web.enabled=false"),
|
||||
false, "found property endpoints.foo.web.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("foo", true,
|
||||
EndpointDelivery.WEB, "endpoints.default.enabled=true",
|
||||
"endpoints.default.web.enabled=true", "endpoints.default.jmx.enabled=true",
|
||||
"endpoints.foo.enabled=true", "endpoints.foo.web.enabled=false");
|
||||
validate(enablement, false, "found property endpoints.foo.web.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificDisabledByDefaultWithAnnotationFlag() {
|
||||
validate(determineEnablement("bar", false, EndpointType.WEB), false,
|
||||
"endpoint 'bar' (web) is disabled by default");
|
||||
EndpointEnablement enablement = getEndpointEnablement("bar", false,
|
||||
EndpointDelivery.WEB);
|
||||
validate(enablement, false, "endpoint 'bar' (web) is disabled by default");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificDisabledByDefaultWithAnnotationFlagEvenWithGeneralProperty() {
|
||||
validate(
|
||||
determineEnablement("bar", false, EndpointType.WEB,
|
||||
"endpoints.default.enabled=true"),
|
||||
false, "endpoint 'bar' (web) is disabled by default");
|
||||
EndpointEnablement enablement = getEndpointEnablement("bar", false,
|
||||
EndpointDelivery.WEB, "endpoints.default.enabled=true");
|
||||
validate(enablement, false, "endpoint 'bar' (web) is disabled by default");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificDisabledByDefaultWithAnnotationFlagEvenWithGeneralWebProperty() {
|
||||
validate(
|
||||
determineEnablement("bar", false, EndpointType.WEB,
|
||||
"endpoints.default.web.enabled=true"),
|
||||
false, "endpoint 'bar' (web) is disabled by default");
|
||||
EndpointEnablement enablement = getEndpointEnablement("bar", false,
|
||||
EndpointDelivery.WEB, "endpoints.default.web.enabled=true");
|
||||
validate(enablement, false, "endpoint 'bar' (web) is disabled by default");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificDisabledByDefaultWithAnnotationFlagEvenWithGeneralJmxProperty() {
|
||||
validate(
|
||||
determineEnablement("bar", false, EndpointType.WEB,
|
||||
"endpoints.default.jmx.enabled=true"),
|
||||
false, "endpoint 'bar' (web) is disabled by default");
|
||||
EndpointEnablement enablement = getEndpointEnablement("bar", false,
|
||||
EndpointDelivery.WEB, "endpoints.default.jmx.enabled=true");
|
||||
validate(enablement, false, "endpoint 'bar' (web) is disabled by default");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificEnabledOverrideWithAndAnnotationFlagAndEndpointProperty() {
|
||||
validate(
|
||||
determineEnablement("bar", false, EndpointType.WEB,
|
||||
"endpoints.bar.enabled=true"),
|
||||
true, "found property endpoints.bar.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("bar", false,
|
||||
EndpointDelivery.WEB, "endpoints.bar.enabled=true");
|
||||
validate(enablement, true, "found property endpoints.bar.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificEnabledOverrideWithAndAnnotationFlagAndTechProperty() {
|
||||
validate(
|
||||
determineEnablement("bar", false, EndpointType.WEB,
|
||||
"endpoints.bar.web.enabled=true"),
|
||||
true, "found property endpoints.bar.web.enabled");
|
||||
EndpointEnablement enablement = getEndpointEnablement("bar", false,
|
||||
EndpointDelivery.WEB, "endpoints.bar.web.enabled=true");
|
||||
validate(enablement, true, "found property endpoints.bar.web.enabled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificEnabledOverrideWithAndAnnotationFlagHasNoEffectWithUnrelatedTechProperty() {
|
||||
validate(
|
||||
determineEnablement("bar", false, EndpointType.WEB,
|
||||
"endpoints.bar.jmx.enabled=true"),
|
||||
false, "endpoint 'bar' (web) is disabled by default");
|
||||
EndpointEnablement enablement = getEndpointEnablement("bar", false,
|
||||
EndpointDelivery.WEB, "endpoints.bar.jmx.enabled=true");
|
||||
validate(enablement, false, "endpoint 'bar' (web) is disabled by default");
|
||||
}
|
||||
|
||||
private EndpointEnablement getEndpointEnablement(String id, boolean enabledByDefault,
|
||||
String... environment) {
|
||||
return getEndpointEnablement(id, enabledByDefault, null, environment);
|
||||
}
|
||||
|
||||
private EndpointEnablement getEndpointEnablement(String id, boolean enabledByDefault,
|
||||
EndpointDelivery delivery, String... environment) {
|
||||
MockEnvironment env = new MockEnvironment();
|
||||
TestPropertyValues.of(environment).applyTo(env);
|
||||
EndpointEnablementProvider provider = new EndpointEnablementProvider(env);
|
||||
return provider.getEndpointEnablement(id, enabledByDefault, delivery);
|
||||
}
|
||||
|
||||
private void validate(EndpointEnablement enablement, boolean enabled,
|
||||
|
|
@ -343,17 +349,4 @@ public class EndpointEnablementProviderTests {
|
|||
}
|
||||
}
|
||||
|
||||
private EndpointEnablement determineEnablement(String id, boolean enabledByDefault,
|
||||
String... environment) {
|
||||
return determineEnablement(id, enabledByDefault, null, environment);
|
||||
}
|
||||
|
||||
private EndpointEnablement determineEnablement(String id, boolean enabledByDefault,
|
||||
EndpointType type, String... environment) {
|
||||
MockEnvironment env = new MockEnvironment();
|
||||
TestPropertyValues.of(environment).applyTo(env);
|
||||
EndpointEnablementProvider provider = new EndpointEnablementProvider(env);
|
||||
return provider.getEndpointEnablement(id, enabledByDefault, type);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import java.util.Map;
|
|||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.endpoint.EndpointInfo;
|
||||
import org.springframework.boot.endpoint.EndpointOperationType;
|
||||
import org.springframework.boot.endpoint.OperationType;
|
||||
import org.springframework.boot.endpoint.web.OperationRequestPredicate;
|
||||
import org.springframework.boot.endpoint.web.WebEndpointHttpMethod;
|
||||
import org.springframework.boot.endpoint.web.WebEndpointOperation;
|
||||
|
|
@ -136,7 +136,7 @@ public class RequestMappingEndpointTests {
|
|||
WebEndpointHttpMethod.GET, Collections.singletonList("application/json"),
|
||||
Collections.singletonList("application/json"));
|
||||
WebEndpointOperation operation = new WebEndpointOperation(
|
||||
EndpointOperationType.READ, (arguments) -> "Invoked", true,
|
||||
OperationType.READ, (arguments) -> "Invoked", true,
|
||||
requestPredicate, "test");
|
||||
WebEndpointServletHandlerMapping mapping = new WebEndpointServletHandlerMapping(
|
||||
"application", Collections.singleton(new EndpointInfo<>("test", true,
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ package org.springframework.boot.endpoint;
|
|||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
|
@ -32,6 +32,7 @@ import org.springframework.context.ApplicationContext;
|
|||
import org.springframework.core.MethodIntrospector;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
|
|
@ -45,7 +46,7 @@ import org.springframework.util.ObjectUtils;
|
|||
* @author Stephane Nicoll
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public abstract class AnnotationEndpointDiscoverer<T extends EndpointOperation, K>
|
||||
public abstract class AnnotationEndpointDiscoverer<T extends Operation, K>
|
||||
implements EndpointDiscoverer<T> {
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
|
|
@ -69,15 +70,15 @@ public abstract class AnnotationEndpointDiscoverer<T extends EndpointOperation,
|
|||
/**
|
||||
* Perform endpoint discovery, including discovery and merging of extensions.
|
||||
* @param extensionType the annotation type of the extension
|
||||
* @param endpointType the {@link EndpointType} that should be considered
|
||||
* @param delivery the {@link EndpointDelivery} that should be considered
|
||||
* @return the list of {@link EndpointInfo EndpointInfos} that describes the
|
||||
* discovered endpoints matching the specified {@link EndpointType}
|
||||
* discovered endpoints matching the specified {@link EndpointDelivery}
|
||||
*/
|
||||
protected Collection<EndpointInfoDescriptor<T, K>> discoverEndpointsWithExtension(
|
||||
Class<? extends Annotation> extensionType, EndpointType endpointType) {
|
||||
Map<Class<?>, EndpointInfo<T>> endpoints = discoverGenericEndpoints(endpointType);
|
||||
protected Collection<EndpointInfoDescriptor<T, K>> discoverEndpoints(
|
||||
Class<? extends Annotation> extensionType, EndpointDelivery delivery) {
|
||||
Map<Class<?>, EndpointInfo<T>> endpoints = discoverEndpoints(delivery);
|
||||
Map<Class<?>, EndpointExtensionInfo<T>> extensions = discoverExtensions(endpoints,
|
||||
extensionType, endpointType);
|
||||
extensionType, delivery);
|
||||
Collection<EndpointInfoDescriptor<T, K>> result = new ArrayList<>();
|
||||
endpoints.forEach((endpointClass, endpointInfo) -> {
|
||||
EndpointExtensionInfo<T> extension = extensions.remove(endpointClass);
|
||||
|
|
@ -86,169 +87,156 @@ public abstract class AnnotationEndpointDiscoverer<T extends EndpointOperation,
|
|||
return result;
|
||||
}
|
||||
|
||||
private EndpointInfoDescriptor<T, K> createDescriptor(Class<?> endpointType,
|
||||
EndpointInfo<T> endpoint, EndpointExtensionInfo<T> extension) {
|
||||
Map<OperationKey<K>, List<T>> endpointOperations = indexOperations(
|
||||
endpoint.getId(), endpointType, endpoint.getOperations());
|
||||
private Map<Class<?>, EndpointInfo<T>> discoverEndpoints(EndpointDelivery delivery) {
|
||||
String[] beanNames = this.applicationContext
|
||||
.getBeanNamesForAnnotation(Endpoint.class);
|
||||
Map<Class<?>, EndpointInfo<T>> endpoints = new LinkedHashMap<>();
|
||||
Map<String, EndpointInfo<T>> endpointsById = new LinkedHashMap<>();
|
||||
for (String beanName : beanNames) {
|
||||
Class<?> beanType = this.applicationContext.getType(beanName);
|
||||
AnnotationAttributes attributes = AnnotatedElementUtils
|
||||
.findMergedAnnotationAttributes(beanType, Endpoint.class, true, true);
|
||||
if (isDeliveredOver(attributes, delivery)) {
|
||||
EndpointInfo<T> info = createEndpointInfo(beanName, beanType, attributes);
|
||||
EndpointInfo<T> previous = endpointsById.putIfAbsent(info.getId(), info);
|
||||
Assert.state(previous == null, () -> "Found two endpoints with the id '"
|
||||
+ info.getId() + "': " + info + " and " + previous);
|
||||
endpoints.put(beanType, info);
|
||||
}
|
||||
}
|
||||
return endpoints;
|
||||
}
|
||||
|
||||
private EndpointInfo<T> createEndpointInfo(String beanName, Class<?> beanType,
|
||||
AnnotationAttributes attributes) {
|
||||
String id = attributes.getString("id");
|
||||
boolean enabledByDefault = attributes.getBoolean("enabledByDefault");
|
||||
Map<Method, T> operations = discoverOperations(id, beanName, beanType);
|
||||
return new EndpointInfo<>(id, enabledByDefault, operations.values());
|
||||
}
|
||||
|
||||
private Map<Class<?>, EndpointExtensionInfo<T>> discoverExtensions(
|
||||
Map<Class<?>, EndpointInfo<T>> endpoints,
|
||||
Class<? extends Annotation> extensionType, EndpointDelivery delivery) {
|
||||
if (extensionType == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
String[] beanNames = this.applicationContext
|
||||
.getBeanNamesForAnnotation(extensionType);
|
||||
Map<Class<?>, EndpointExtensionInfo<T>> extensions = new HashMap<>();
|
||||
for (String beanName : beanNames) {
|
||||
Class<?> beanType = this.applicationContext.getType(beanName);
|
||||
Class<?> endpointType = getEndpointType(extensionType, beanType);
|
||||
AnnotationAttributes endpointAttributes = AnnotatedElementUtils
|
||||
.getMergedAnnotationAttributes(endpointType, Endpoint.class);
|
||||
Assert.state(isDeliveredOver(endpointAttributes, delivery),
|
||||
"Invalid extension " + beanType.getName() + "': endpoint '"
|
||||
+ endpointType.getName()
|
||||
+ "' does not support such extension");
|
||||
EndpointInfo<T> info = getEndpointInfo(endpoints, beanType, endpointType);
|
||||
Map<Method, T> operations = discoverOperations(info.getId(), beanName,
|
||||
beanType);
|
||||
EndpointExtensionInfo<T> extension = new EndpointExtensionInfo<>(beanType,
|
||||
operations.values());
|
||||
EndpointExtensionInfo<T> previous = extensions.putIfAbsent(endpointType,
|
||||
extension);
|
||||
Assert.state(previous == null,
|
||||
() -> "Found two extensions for the same endpoint '"
|
||||
+ endpointType.getName() + "': "
|
||||
+ extension.getExtensionType().getName() + " and "
|
||||
+ previous.getExtensionType().getName());
|
||||
}
|
||||
return extensions;
|
||||
|
||||
}
|
||||
|
||||
private EndpointInfo<T> getEndpointInfo(Map<Class<?>, EndpointInfo<T>> endpoints,
|
||||
Class<?> beanType, Class<?> endpointClass) {
|
||||
EndpointInfo<T> endpoint = endpoints.get(endpointClass);
|
||||
Assert.state(endpoint != null, "Invalid extension '" + beanType.getName()
|
||||
+ "': no endpoint found with type '" + endpointClass.getName() + "'");
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
private Class<?> getEndpointType(Class<? extends Annotation> extensionType,
|
||||
Class<?> beanType) {
|
||||
AnnotationAttributes attributes = AnnotatedElementUtils
|
||||
.getMergedAnnotationAttributes(beanType, extensionType);
|
||||
return (Class<?>) attributes.get("endpoint");
|
||||
}
|
||||
|
||||
private EndpointInfoDescriptor<T, K> createDescriptor(Class<?> type,
|
||||
EndpointInfo<T> info, EndpointExtensionInfo<T> extension) {
|
||||
Map<OperationKey<K>, List<T>> operations = indexOperations(info.getId(), type,
|
||||
info.getOperations());
|
||||
if (extension != null) {
|
||||
endpointOperations.putAll(indexOperations(endpoint.getId(),
|
||||
extension.getEndpointExtensionType(), extension.getOperations()));
|
||||
return new EndpointInfoDescriptor<>(mergeEndpoint(endpoint, extension),
|
||||
endpointOperations);
|
||||
}
|
||||
else {
|
||||
return new EndpointInfoDescriptor<>(endpoint, endpointOperations);
|
||||
operations.putAll(indexOperations(info.getId(), extension.getExtensionType(),
|
||||
extension.getOperations()));
|
||||
return new EndpointInfoDescriptor<>(mergeEndpoint(info, extension),
|
||||
operations);
|
||||
}
|
||||
return new EndpointInfoDescriptor<>(info, operations);
|
||||
}
|
||||
|
||||
private EndpointInfo<T> mergeEndpoint(EndpointInfo<T> endpoint,
|
||||
EndpointExtensionInfo<T> extension) {
|
||||
Map<K, T> operations = new HashMap<>();
|
||||
Consumer<T> operationConsumer = (operation) -> operations
|
||||
Consumer<T> consumer = (operation) -> operations
|
||||
.put(this.operationKeyFactory.apply(operation), operation);
|
||||
endpoint.getOperations().forEach(operationConsumer);
|
||||
extension.getOperations().forEach(operationConsumer);
|
||||
endpoint.getOperations().forEach(consumer);
|
||||
extension.getOperations().forEach(consumer);
|
||||
return new EndpointInfo<>(endpoint.getId(), endpoint.isEnabledByDefault(),
|
||||
operations.values());
|
||||
}
|
||||
|
||||
private Map<OperationKey<K>, List<T>> indexOperations(String endpointId,
|
||||
Class<?> target, Collection<T> operations) {
|
||||
LinkedMultiValueMap<OperationKey<K>, T> operationByKey = new LinkedMultiValueMap<>();
|
||||
operations
|
||||
.forEach(
|
||||
(operation) -> operationByKey.add(
|
||||
new OperationKey<>(endpointId, target,
|
||||
this.operationKeyFactory.apply(operation)),
|
||||
operation));
|
||||
return operationByKey;
|
||||
LinkedMultiValueMap<OperationKey<K>, T> result = new LinkedMultiValueMap<>();
|
||||
operations.forEach((operation) -> {
|
||||
K key = this.operationKeyFactory.apply(operation);
|
||||
result.add(new OperationKey<>(endpointId, target, key), operation);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<Class<?>, EndpointInfo<T>> discoverGenericEndpoints(
|
||||
EndpointType endpointType) {
|
||||
String[] endpointBeanNames = this.applicationContext
|
||||
.getBeanNamesForAnnotation(Endpoint.class);
|
||||
Map<String, EndpointInfo<T>> endpointsById = new HashMap<>();
|
||||
Map<Class<?>, EndpointInfo<T>> endpointsByClass = new HashMap<>();
|
||||
for (String beanName : endpointBeanNames) {
|
||||
Class<?> beanType = this.applicationContext.getType(beanName);
|
||||
AnnotationAttributes endpointAttributes = AnnotatedElementUtils
|
||||
.findMergedAnnotationAttributes(beanType, Endpoint.class, true, true);
|
||||
String endpointId = endpointAttributes.getString("id");
|
||||
if (matchEndpointType(endpointAttributes, endpointType)) {
|
||||
EndpointInfo<T> endpointInfo = createEndpointInfo(endpointsById, beanName,
|
||||
beanType, endpointAttributes, endpointId);
|
||||
endpointsByClass.put(beanType, endpointInfo);
|
||||
}
|
||||
}
|
||||
return endpointsByClass;
|
||||
}
|
||||
|
||||
private EndpointInfo<T> createEndpointInfo(Map<String, EndpointInfo<T>> endpointsById,
|
||||
String beanName, Class<?> beanType, AnnotationAttributes endpointAttributes,
|
||||
String endpointId) {
|
||||
Map<Method, T> operationMethods = discoverOperations(endpointId, beanName,
|
||||
beanType);
|
||||
EndpointInfo<T> endpointInfo = new EndpointInfo<>(endpointId,
|
||||
endpointAttributes.getBoolean("enabledByDefault"),
|
||||
operationMethods.values());
|
||||
EndpointInfo<T> previous = endpointsById.putIfAbsent(endpointInfo.getId(),
|
||||
endpointInfo);
|
||||
if (previous != null) {
|
||||
throw new IllegalStateException("Found two endpoints with the id '"
|
||||
+ endpointInfo.getId() + "': " + endpointInfo + " and " + previous);
|
||||
}
|
||||
return endpointInfo;
|
||||
}
|
||||
|
||||
private Map<Class<?>, EndpointExtensionInfo<T>> discoverExtensions(
|
||||
Map<Class<?>, EndpointInfo<T>> endpoints,
|
||||
Class<? extends Annotation> extensionType, EndpointType endpointType) {
|
||||
if (extensionType == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
String[] extensionBeanNames = this.applicationContext
|
||||
.getBeanNamesForAnnotation(extensionType);
|
||||
Map<Class<?>, EndpointExtensionInfo<T>> extensionsByEndpoint = new HashMap<>();
|
||||
for (String beanName : extensionBeanNames) {
|
||||
Class<?> beanType = this.applicationContext.getType(beanName);
|
||||
AnnotationAttributes extensionAttributes = AnnotatedElementUtils
|
||||
.getMergedAnnotationAttributes(beanType, extensionType);
|
||||
Class<?> endpointClass = (Class<?>) extensionAttributes.get("endpoint");
|
||||
AnnotationAttributes endpointAttributes = AnnotatedElementUtils
|
||||
.getMergedAnnotationAttributes(endpointClass, Endpoint.class);
|
||||
if (!matchEndpointType(endpointAttributes, endpointType)) {
|
||||
throw new IllegalStateException(String.format(
|
||||
"Invalid extension %s': "
|
||||
+ "endpoint '%s' does not support such extension",
|
||||
beanType.getName(), endpointClass.getName()));
|
||||
}
|
||||
EndpointInfo<T> endpoint = endpoints.get(endpointClass);
|
||||
if (endpoint == null) {
|
||||
throw new IllegalStateException(String.format(
|
||||
"Invalid extension '%s': no endpoint found with type '%s'",
|
||||
beanType.getName(), endpointClass.getName()));
|
||||
}
|
||||
Map<Method, T> operationMethods = discoverOperations(endpoint.getId(),
|
||||
beanName, beanType);
|
||||
EndpointExtensionInfo<T> extension = new EndpointExtensionInfo<>(beanType,
|
||||
operationMethods.values());
|
||||
EndpointExtensionInfo<T> previous = extensionsByEndpoint
|
||||
.putIfAbsent(endpointClass, extension);
|
||||
if (previous != null) {
|
||||
throw new IllegalStateException(
|
||||
"Found two extensions for the same endpoint '"
|
||||
+ endpointClass.getName() + "': "
|
||||
+ extension.getEndpointExtensionType().getName() + " and "
|
||||
+ previous.getEndpointExtensionType().getName());
|
||||
}
|
||||
}
|
||||
return extensionsByEndpoint;
|
||||
}
|
||||
|
||||
private boolean matchEndpointType(AnnotationAttributes endpointAttributes,
|
||||
EndpointType endpointType) {
|
||||
if (endpointType == null) {
|
||||
private boolean isDeliveredOver(AnnotationAttributes attributes,
|
||||
EndpointDelivery delivery) {
|
||||
if (delivery == null) {
|
||||
return true;
|
||||
}
|
||||
Object types = endpointAttributes.get("types");
|
||||
if (ObjectUtils.isEmpty(types)) {
|
||||
return true;
|
||||
}
|
||||
return Arrays.stream((EndpointType[]) types)
|
||||
.anyMatch((t) -> t.equals(endpointType));
|
||||
EndpointDelivery[] supported = (EndpointDelivery[]) attributes.get("delivery");
|
||||
return ObjectUtils.isEmpty(supported)
|
||||
|| ObjectUtils.containsElement(supported, delivery);
|
||||
}
|
||||
|
||||
private Map<Method, T> discoverOperations(String endpointId, String beanName,
|
||||
Class<?> beanType) {
|
||||
return MethodIntrospector.selectMethods(beanType,
|
||||
private Map<Method, T> discoverOperations(String id, String name, Class<?> type) {
|
||||
return MethodIntrospector.selectMethods(type,
|
||||
(MethodIntrospector.MetadataLookup<T>) (
|
||||
method) -> createOperationIfPossible(endpointId, beanName,
|
||||
method));
|
||||
method) -> createOperationIfPossible(id, name, method));
|
||||
}
|
||||
|
||||
private T createOperationIfPossible(String endpointId, String beanName,
|
||||
Method method) {
|
||||
T readOperation = createReadOperationIfPossible(endpointId, beanName, method);
|
||||
return readOperation != null ? readOperation
|
||||
: createWriteOperationIfPossible(endpointId, beanName, method);
|
||||
return (readOperation != null ? readOperation
|
||||
: createWriteOperationIfPossible(endpointId, beanName, method));
|
||||
}
|
||||
|
||||
private T createReadOperationIfPossible(String endpointId, String beanName,
|
||||
Method method) {
|
||||
return createOperationIfPossible(endpointId, beanName, method,
|
||||
ReadOperation.class, EndpointOperationType.READ);
|
||||
ReadOperation.class, OperationType.READ);
|
||||
}
|
||||
|
||||
private T createWriteOperationIfPossible(String endpointId, String beanName,
|
||||
Method method) {
|
||||
return createOperationIfPossible(endpointId, beanName, method,
|
||||
WriteOperation.class, EndpointOperationType.WRITE);
|
||||
WriteOperation.class, OperationType.WRITE);
|
||||
}
|
||||
|
||||
private T createOperationIfPossible(String endpointId, String beanName, Method method,
|
||||
Class<? extends Annotation> operationAnnotation,
|
||||
EndpointOperationType operationType) {
|
||||
OperationType operationType) {
|
||||
AnnotationAttributes operationAttributes = AnnotatedElementUtils
|
||||
.getMergedAnnotationAttributes(method, operationAnnotation);
|
||||
if (operationAttributes == null) {
|
||||
|
|
@ -262,9 +250,9 @@ public abstract class AnnotationEndpointDiscoverer<T extends EndpointOperation,
|
|||
}
|
||||
|
||||
private long determineTimeToLive(CachingConfiguration cachingConfiguration,
|
||||
EndpointOperationType operationType, Method method) {
|
||||
OperationType operationType, Method method) {
|
||||
if (cachingConfiguration != null && cachingConfiguration.getTimeToLive() > 0
|
||||
&& operationType == EndpointOperationType.READ
|
||||
&& operationType == OperationType.READ
|
||||
&& method.getParameters().length == 0) {
|
||||
return cachingConfiguration.getTimeToLive();
|
||||
}
|
||||
|
|
@ -272,13 +260,13 @@ public abstract class AnnotationEndpointDiscoverer<T extends EndpointOperation,
|
|||
}
|
||||
|
||||
/**
|
||||
* An {@code EndpointOperationFactory} creates an {@link EndpointOperation} for an
|
||||
* operation on an endpoint.
|
||||
* An {@code EndpointOperationFactory} creates an {@link Operation} for an operation
|
||||
* on an endpoint.
|
||||
*
|
||||
* @param <T> the {@link EndpointOperation} type
|
||||
* @param <T> the {@link Operation} type
|
||||
*/
|
||||
@FunctionalInterface
|
||||
protected interface EndpointOperationFactory<T extends EndpointOperation> {
|
||||
protected interface EndpointOperationFactory<T extends Operation> {
|
||||
|
||||
/**
|
||||
* Creates an {@code EndpointOperation} for an operation on an endpoint.
|
||||
|
|
@ -291,8 +279,8 @@ public abstract class AnnotationEndpointDiscoverer<T extends EndpointOperation,
|
|||
* @return the operation info that describes the operation
|
||||
*/
|
||||
T createOperation(String endpointId, AnnotationAttributes operationAttributes,
|
||||
Object target, Method operationMethod,
|
||||
EndpointOperationType operationType, long timeToLive);
|
||||
Object target, Method operationMethod, OperationType operationType,
|
||||
long timeToLive);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -300,20 +288,19 @@ public abstract class AnnotationEndpointDiscoverer<T extends EndpointOperation,
|
|||
* Describes a tech-specific extension of an endpoint.
|
||||
* @param <T> the type of the operation
|
||||
*/
|
||||
private static final class EndpointExtensionInfo<T extends EndpointOperation> {
|
||||
private static final class EndpointExtensionInfo<T extends Operation> {
|
||||
|
||||
private final Class<?> endpointExtensionType;
|
||||
private final Class<?> extensionType;
|
||||
|
||||
private final Collection<T> operations;
|
||||
|
||||
private EndpointExtensionInfo(Class<?> endpointExtensionType,
|
||||
Collection<T> operations) {
|
||||
this.endpointExtensionType = endpointExtensionType;
|
||||
private EndpointExtensionInfo(Class<?> extensionType, Collection<T> operations) {
|
||||
this.extensionType = extensionType;
|
||||
this.operations = operations;
|
||||
}
|
||||
|
||||
private Class<?> getEndpointExtensionType() {
|
||||
return this.endpointExtensionType;
|
||||
private Class<?> getExtensionType() {
|
||||
return this.extensionType;
|
||||
}
|
||||
|
||||
private Collection<T> getOperations() {
|
||||
|
|
@ -328,7 +315,7 @@ public abstract class AnnotationEndpointDiscoverer<T extends EndpointOperation,
|
|||
* @param <T> the type of the operation
|
||||
* @param <K> the type of the operation key
|
||||
*/
|
||||
protected static class EndpointInfoDescriptor<T extends EndpointOperation, K> {
|
||||
protected static class EndpointInfoDescriptor<T extends Operation, K> {
|
||||
|
||||
private final EndpointInfo<T> endpointInfo;
|
||||
|
||||
|
|
@ -377,22 +364,18 @@ public abstract class AnnotationEndpointDiscoverer<T extends EndpointOperation,
|
|||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
if (o == this) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
OperationKey<?> that = (OperationKey<?>) o;
|
||||
|
||||
if (!this.endpointId.equals(that.endpointId)) {
|
||||
return false;
|
||||
}
|
||||
if (!this.endpointType.equals(that.endpointType)) {
|
||||
return false;
|
||||
}
|
||||
return this.key.equals(that.key);
|
||||
OperationKey<?> other = (OperationKey<?>) o;
|
||||
Boolean result = true;
|
||||
result = result && this.endpointId.equals(other.endpointId);
|
||||
result = result && this.endpointType.equals(other.endpointType);
|
||||
result = result && this.key.equals(other.key);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
package org.springframework.boot.endpoint;
|
||||
|
||||
/**
|
||||
* {@link EndpointPathResolver} implementation that does not support
|
||||
* resolving endpoint paths.
|
||||
* {@link EndpointPathResolver} implementation that does not support resolving endpoint
|
||||
* paths.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @since 2.0.0
|
||||
|
|
@ -31,4 +31,3 @@ public class DefaultEndpointPathResolver implements EndpointPathResolver {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,11 +41,11 @@ public @interface Endpoint {
|
|||
String id();
|
||||
|
||||
/**
|
||||
* Defines the endpoint {@link EndpointType types} that should be exposed. By default,
|
||||
* all types are exposed.
|
||||
* @return the endpoint types to expose
|
||||
* Defines the {@link EndpointDelivery delivery technologies} over which the
|
||||
* endpoint should be delivered over. By default, all technologies are supported.
|
||||
* @return the supported endpoint delivery technologies
|
||||
*/
|
||||
EndpointType[] types() default {};
|
||||
EndpointDelivery[] delivery() default {};
|
||||
|
||||
/**
|
||||
* Whether or not the endpoint is enabled by default.
|
||||
|
|
|
|||
|
|
@ -17,12 +17,12 @@
|
|||
package org.springframework.boot.endpoint;
|
||||
|
||||
/**
|
||||
* An enumeration of the available {@link Endpoint} types.
|
||||
* An enumeration of the available {@link Endpoint} delivery technologies.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public enum EndpointType {
|
||||
public enum EndpointDelivery {
|
||||
|
||||
/**
|
||||
* Expose the endpoint as a JMX MBean.
|
||||
|
|
@ -36,11 +36,12 @@ public enum EndpointType {
|
|||
|
||||
private final boolean enabledByDefault;
|
||||
|
||||
EndpointType(boolean enabledByDefault) {
|
||||
EndpointDelivery(boolean enabledByDefault) {
|
||||
this.enabledByDefault = enabledByDefault;
|
||||
}
|
||||
|
||||
public boolean isEnabledByDefault() {
|
||||
return this.enabledByDefault;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@ import java.util.Collection;
|
|||
* @since 2.0.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface EndpointDiscoverer<T extends EndpointOperation> {
|
||||
public interface EndpointDiscoverer<T extends Operation> {
|
||||
|
||||
/**
|
||||
* Perform endpoint discovery.
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import java.util.Collection;
|
|||
* @author Andy Wilkinson
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class EndpointInfo<T extends EndpointOperation> {
|
||||
public class EndpointInfo<T extends Operation> {
|
||||
|
||||
private final String id;
|
||||
|
||||
|
|
|
|||
|
|
@ -22,11 +22,11 @@ package org.springframework.boot.endpoint;
|
|||
* @author Andy Wilkinson
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class EndpointOperation {
|
||||
public class Operation {
|
||||
|
||||
private final EndpointOperationType type;
|
||||
private final OperationType type;
|
||||
|
||||
private final OperationInvoker operationInvoker;
|
||||
private final OperationInvoker invoker;
|
||||
|
||||
private final boolean blocking;
|
||||
|
||||
|
|
@ -37,18 +37,18 @@ public class EndpointOperation {
|
|||
* @param operationInvoker used to perform the operation
|
||||
* @param blocking whether or not this is a blocking operation
|
||||
*/
|
||||
public EndpointOperation(EndpointOperationType type,
|
||||
public Operation(OperationType type,
|
||||
OperationInvoker operationInvoker, boolean blocking) {
|
||||
this.type = type;
|
||||
this.operationInvoker = operationInvoker;
|
||||
this.invoker = operationInvoker;
|
||||
this.blocking = blocking;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link EndpointOperationType type} of the operation.
|
||||
* Returns the {@link OperationType type} of the operation.
|
||||
* @return the type
|
||||
*/
|
||||
public EndpointOperationType getType() {
|
||||
public OperationType getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
|
|
@ -57,8 +57,8 @@ public class EndpointOperation {
|
|||
* operation.
|
||||
* @return the operation invoker
|
||||
*/
|
||||
public OperationInvoker getOperationInvoker() {
|
||||
return this.operationInvoker;
|
||||
public OperationInvoker getInvoker() {
|
||||
return this.invoker;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -22,7 +22,7 @@ package org.springframework.boot.endpoint;
|
|||
* @author Andy Wilkinson
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public enum EndpointOperationType {
|
||||
public enum OperationType {
|
||||
|
||||
/**
|
||||
* A read operation.
|
||||
|
|
@ -47,7 +47,6 @@ public class ParameterMappingException extends RuntimeException {
|
|||
|
||||
/**
|
||||
* Returns the input that was to be mapped.
|
||||
*
|
||||
* @return the input
|
||||
*/
|
||||
public Object getInput() {
|
||||
|
|
@ -56,7 +55,6 @@ public class ParameterMappingException extends RuntimeException {
|
|||
|
||||
/**
|
||||
* Returns the type to be mapped to.
|
||||
*
|
||||
* @return the type
|
||||
*/
|
||||
public Class<?> getType() {
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ public class ReflectiveOperationInvoker implements OperationInvoker {
|
|||
* Creates a new {code ReflectiveOperationInvoker} that will invoke the given
|
||||
* {@code method} on the given {@code target}. The given {@code parameterMapper} will
|
||||
* be used to map parameters to the required types.
|
||||
*
|
||||
* @param parameterMapper the parameter mapper
|
||||
* @param target the target of the reflective call
|
||||
* @param method the method to call
|
||||
|
|
|
|||
|
|
@ -74,16 +74,12 @@ public class EndpointMBean implements DynamicMBean {
|
|||
@Override
|
||||
public Object invoke(String actionName, Object[] params, String[] signature)
|
||||
throws MBeanException, ReflectionException {
|
||||
JmxEndpointOperation operationInfo = this.endpointInfo.getOperations()
|
||||
JmxEndpointOperation operation = this.endpointInfo.getOperations()
|
||||
.get(actionName);
|
||||
if (operationInfo != null) {
|
||||
Map<String, Object> arguments = new HashMap<>();
|
||||
List<JmxEndpointOperationParameterInfo> parameters = operationInfo
|
||||
.getParameters();
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
arguments.put(parameters.get(i).getName(), params[i]);
|
||||
}
|
||||
Object result = operationInfo.getOperationInvoker().invoke(arguments);
|
||||
if (operation != null) {
|
||||
Map<String, Object> arguments = getArguments(params,
|
||||
operation.getParameters());
|
||||
Object result = operation.getInvoker().invoke(arguments);
|
||||
if (REACTOR_PRESENT) {
|
||||
result = ReactiveHandler.handle(result);
|
||||
}
|
||||
|
|
@ -94,6 +90,15 @@ public class EndpointMBean implements DynamicMBean {
|
|||
this.endpointInfo.getEndpointId(), actionName)));
|
||||
}
|
||||
|
||||
private Map<String, Object> getArguments(Object[] params,
|
||||
List<JmxEndpointOperationParameterInfo> parameters) {
|
||||
Map<String, Object> arguments = new HashMap<>();
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
arguments.put(parameters.get(i).getName(), params[i]);
|
||||
}
|
||||
return arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String attribute)
|
||||
throws AttributeNotFoundException, MBeanException, ReflectionException {
|
||||
|
|
|
|||
|
|
@ -21,11 +21,11 @@ import java.util.Map;
|
|||
import javax.management.MBeanInfo;
|
||||
|
||||
import org.springframework.boot.endpoint.EndpointInfo;
|
||||
import org.springframework.boot.endpoint.EndpointOperation;
|
||||
import org.springframework.boot.endpoint.Operation;
|
||||
|
||||
/**
|
||||
* The {@link MBeanInfo} for a particular {@link EndpointInfo endpoint}. Maps operation
|
||||
* names to an {@link EndpointOperation}.
|
||||
* names to an {@link Operation}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 2.0.0
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import javax.management.modelmbean.ModelMBeanNotificationInfo;
|
|||
import javax.management.modelmbean.ModelMBeanOperationInfo;
|
||||
|
||||
import org.springframework.boot.endpoint.EndpointInfo;
|
||||
import org.springframework.boot.endpoint.EndpointOperationType;
|
||||
import org.springframework.boot.endpoint.OperationType;
|
||||
|
||||
/**
|
||||
* Gathers the management operations of a particular {@link EndpointInfo endpoint}.
|
||||
|
|
@ -61,7 +61,6 @@ class EndpointMBeanInfoAssembler {
|
|||
.toArray(new ModelMBeanOperationInfo[] {});
|
||||
Map<String, JmxEndpointOperation> operationsInfo = new LinkedHashMap<>();
|
||||
operationsMapping.forEach((name, t) -> operationsInfo.put(name, t.operation));
|
||||
|
||||
MBeanInfo info = new ModelMBeanInfoSupport(EndpointMBean.class.getName(),
|
||||
getDescription(endpointInfo), new ModelMBeanAttributeInfo[0],
|
||||
new ModelMBeanConstructorInfo[0], operationsMBeanInfo,
|
||||
|
|
@ -100,11 +99,11 @@ class EndpointMBeanInfoAssembler {
|
|||
.toArray(new MBeanParameterInfo[parameterInfos.size()])));
|
||||
}
|
||||
|
||||
private int mapOperationType(EndpointOperationType type) {
|
||||
if (type == EndpointOperationType.READ) {
|
||||
private int mapOperationType(OperationType type) {
|
||||
if (type == OperationType.READ) {
|
||||
return MBeanOperationInfo.INFO;
|
||||
}
|
||||
if (type == EndpointOperationType.WRITE) {
|
||||
if (type == OperationType.WRITE) {
|
||||
return MBeanOperationInfo.ACTION;
|
||||
}
|
||||
return MBeanOperationInfo.UNKNOWN;
|
||||
|
|
|
|||
|
|
@ -68,24 +68,21 @@ public class EndpointMBeanRegistrar {
|
|||
Assert.notNull(endpoint, "Endpoint must not be null");
|
||||
try {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format(
|
||||
"Registering endpoint with id '%s' to " + "the JMX domain",
|
||||
endpoint.getEndpointId()));
|
||||
logger.debug("Registering endpoint with id '" + endpoint.getEndpointId()
|
||||
+ "' to the JMX domain");
|
||||
}
|
||||
ObjectName objectName = this.objectNameFactory.generate(endpoint);
|
||||
this.mBeanServer.registerMBean(endpoint, objectName);
|
||||
return objectName;
|
||||
}
|
||||
catch (MalformedObjectNameException ex) {
|
||||
throw new IllegalStateException(
|
||||
String.format("Invalid ObjectName for " + "endpoint with id '%s'",
|
||||
endpoint.getEndpointId()),
|
||||
ex);
|
||||
throw new IllegalStateException("Invalid ObjectName for endpoint with id '"
|
||||
+ endpoint.getEndpointId() + "'", ex);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new MBeanExportException(
|
||||
String.format("Failed to register MBean for endpoint with id '%s'",
|
||||
endpoint.getEndpointId()),
|
||||
"Failed to register MBean for endpoint with id '"
|
||||
+ endpoint.getEndpointId() + "'",
|
||||
ex);
|
||||
}
|
||||
}
|
||||
|
|
@ -99,8 +96,8 @@ public class EndpointMBeanRegistrar {
|
|||
public boolean unregisterEndpointMbean(ObjectName objectName) {
|
||||
try {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Unregister endpoint with ObjectName '%s' "
|
||||
+ "from the JMX domain", objectName));
|
||||
logger.debug("Unregister endpoint with ObjectName '" + objectName + "' "
|
||||
+ "from the JMX domain");
|
||||
}
|
||||
this.mBeanServer.unregisterMBean(objectName);
|
||||
return true;
|
||||
|
|
@ -110,8 +107,7 @@ public class EndpointMBeanRegistrar {
|
|||
}
|
||||
catch (MBeanRegistrationException ex) {
|
||||
throw new JmxException(
|
||||
String.format("Failed to unregister MBean with" + "ObjectName '%s'",
|
||||
objectName),
|
||||
"Failed to unregister MBean with ObjectName '" + objectName + "'",
|
||||
ex);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import java.lang.reflect.Method;
|
|||
import java.lang.reflect.Parameter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
|
@ -30,11 +31,11 @@ import org.springframework.boot.endpoint.AnnotationEndpointDiscoverer;
|
|||
import org.springframework.boot.endpoint.CachingConfiguration;
|
||||
import org.springframework.boot.endpoint.CachingOperationInvoker;
|
||||
import org.springframework.boot.endpoint.Endpoint;
|
||||
import org.springframework.boot.endpoint.EndpointDelivery;
|
||||
import org.springframework.boot.endpoint.EndpointInfo;
|
||||
import org.springframework.boot.endpoint.EndpointOperationType;
|
||||
import org.springframework.boot.endpoint.EndpointType;
|
||||
import org.springframework.boot.endpoint.OperationInvoker;
|
||||
import org.springframework.boot.endpoint.OperationParameterMapper;
|
||||
import org.springframework.boot.endpoint.OperationType;
|
||||
import org.springframework.boot.endpoint.ReflectiveOperationInvoker;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
|
|
@ -60,7 +61,6 @@ public class JmxAnnotationEndpointDiscoverer
|
|||
* Creates a new {@link JmxAnnotationEndpointDiscoverer} that will discover
|
||||
* {@link Endpoint endpoints} and {@link JmxEndpointExtension jmx extensions} using
|
||||
* the given {@link ApplicationContext}.
|
||||
*
|
||||
* @param applicationContext the application context
|
||||
* @param parameterMapper the {@link OperationParameterMapper} used to convert
|
||||
* arguments when an operation is invoked
|
||||
|
|
@ -75,8 +75,8 @@ public class JmxAnnotationEndpointDiscoverer
|
|||
|
||||
@Override
|
||||
public Collection<EndpointInfo<JmxEndpointOperation>> discoverEndpoints() {
|
||||
Collection<EndpointInfoDescriptor<JmxEndpointOperation, String>> endpointDescriptors = discoverEndpointsWithExtension(
|
||||
JmxEndpointExtension.class, EndpointType.JMX);
|
||||
Collection<EndpointInfoDescriptor<JmxEndpointOperation, String>> endpointDescriptors = discoverEndpoints(
|
||||
JmxEndpointExtension.class, EndpointDelivery.JMX);
|
||||
verifyThatOperationsHaveDistinctName(endpointDescriptors);
|
||||
return endpointDescriptors.stream().map(EndpointInfoDescriptor::getEndpointInfo)
|
||||
.collect(Collectors.toList());
|
||||
|
|
@ -113,7 +113,7 @@ public class JmxAnnotationEndpointDiscoverer
|
|||
@Override
|
||||
public JmxEndpointOperation createOperation(String endpointId,
|
||||
AnnotationAttributes operationAttributes, Object target, Method method,
|
||||
EndpointOperationType type, long timeToLive) {
|
||||
OperationType type, long timeToLive) {
|
||||
String operationName = method.getName();
|
||||
Class<?> outputType = mapParameterType(method.getReturnType());
|
||||
String description = getDescription(method,
|
||||
|
|
@ -139,29 +139,40 @@ public class JmxAnnotationEndpointDiscoverer
|
|||
}
|
||||
|
||||
private List<JmxEndpointOperationParameterInfo> getParameters(Method method) {
|
||||
List<JmxEndpointOperationParameterInfo> parameters = new ArrayList<>();
|
||||
Parameter[] methodParameters = method.getParameters();
|
||||
if (methodParameters.length == 0) {
|
||||
return parameters;
|
||||
return Collections.emptyList();
|
||||
}
|
||||
ManagedOperationParameter[] managedOperationParameters = jmxAttributeSource
|
||||
.getManagedOperationParameters(method);
|
||||
if (managedOperationParameters.length > 0) {
|
||||
for (int i = 0; i < managedOperationParameters.length; i++) {
|
||||
ManagedOperationParameter mBeanParameter = managedOperationParameters[i];
|
||||
Parameter methodParameter = methodParameters[i];
|
||||
parameters.add(new JmxEndpointOperationParameterInfo(
|
||||
mBeanParameter.getName(),
|
||||
mapParameterType(methodParameter.getType()),
|
||||
mBeanParameter.getDescription()));
|
||||
}
|
||||
if (managedOperationParameters.length == 0) {
|
||||
return getParametersInfo(methodParameters);
|
||||
}
|
||||
else {
|
||||
for (Parameter parameter : methodParameters) {
|
||||
parameters.add(
|
||||
new JmxEndpointOperationParameterInfo(parameter.getName(),
|
||||
mapParameterType(parameter.getType()), null));
|
||||
}
|
||||
return getParametersInfo(methodParameters, managedOperationParameters);
|
||||
}
|
||||
|
||||
private List<JmxEndpointOperationParameterInfo> getParametersInfo(
|
||||
Parameter[] methodParameters) {
|
||||
List<JmxEndpointOperationParameterInfo> parameters = new ArrayList<>();
|
||||
for (Parameter methodParameter : methodParameters) {
|
||||
String name = methodParameter.getName();
|
||||
Class<?> type = mapParameterType(methodParameter.getType());
|
||||
parameters.add(new JmxEndpointOperationParameterInfo(name, type, null));
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private List<JmxEndpointOperationParameterInfo> getParametersInfo(
|
||||
Parameter[] methodParameters,
|
||||
ManagedOperationParameter[] managedOperationParameters) {
|
||||
List<JmxEndpointOperationParameterInfo> parameters = new ArrayList<>();
|
||||
for (int i = 0; i < managedOperationParameters.length; i++) {
|
||||
ManagedOperationParameter managedOperationParameter = managedOperationParameters[i];
|
||||
Parameter methodParameter = methodParameters[i];
|
||||
parameters.add(new JmxEndpointOperationParameterInfo(
|
||||
managedOperationParameter.getName(),
|
||||
mapParameterType(methodParameter.getType()),
|
||||
managedOperationParameter.getDescription()));
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,11 +51,13 @@ public class JmxEndpointMBeanFactory {
|
|||
*/
|
||||
public Collection<EndpointMBean> createMBeans(
|
||||
Collection<EndpointInfo<JmxEndpointOperation>> endpoints) {
|
||||
return endpoints.stream().map((endpointInfo) -> {
|
||||
EndpointMBeanInfo endpointMBeanInfo = this.assembler
|
||||
.createEndpointMBeanInfo(endpointInfo);
|
||||
return new EndpointMBean(this.resultMapper::mapResponse, endpointMBeanInfo);
|
||||
}).collect(Collectors.toList());
|
||||
return endpoints.stream().map(this::createMBean).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private EndpointMBean createMBean(EndpointInfo<JmxEndpointOperation> endpointInfo) {
|
||||
EndpointMBeanInfo endpointMBeanInfo = this.assembler
|
||||
.createEndpointMBeanInfo(endpointInfo);
|
||||
return new EndpointMBean(this.resultMapper::mapResponse, endpointMBeanInfo);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@ package org.springframework.boot.endpoint.jmx;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.endpoint.EndpointOperation;
|
||||
import org.springframework.boot.endpoint.EndpointOperationType;
|
||||
import org.springframework.boot.endpoint.Operation;
|
||||
import org.springframework.boot.endpoint.OperationInvoker;
|
||||
import org.springframework.boot.endpoint.OperationType;
|
||||
|
||||
/**
|
||||
* An operation on a JMX endpoint.
|
||||
|
|
@ -30,7 +30,7 @@ import org.springframework.boot.endpoint.OperationInvoker;
|
|||
* @author Andy Wilkinson
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class JmxEndpointOperation extends EndpointOperation {
|
||||
public class JmxEndpointOperation extends Operation {
|
||||
|
||||
private final String operationName;
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ public class JmxEndpointOperation extends EndpointOperation {
|
|||
* @param description the description of the operation
|
||||
* @param parameters the parameters of the operation
|
||||
*/
|
||||
public JmxEndpointOperation(EndpointOperationType type, OperationInvoker invoker,
|
||||
public JmxEndpointOperation(OperationType type, OperationInvoker invoker,
|
||||
String operationName, Class<?> outputType, String description,
|
||||
List<JmxEndpointOperationParameterInfo> parameters) {
|
||||
super(type, invoker, true);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ public class EndpointLinksResolver {
|
|||
/**
|
||||
* Resolves links to the operations of the given {code webEndpoints} based on a
|
||||
* request with the given {@code requestUrl}.
|
||||
*
|
||||
* @param webEndpoints the web endpoints
|
||||
* @param requestUrl the url of the request for the endpoint links
|
||||
* @return the links
|
||||
|
|
|
|||
|
|
@ -111,26 +111,16 @@ public class OperationRequestPredicate {
|
|||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
OperationRequestPredicate other = (OperationRequestPredicate) obj;
|
||||
if (!this.consumes.equals(other.consumes)) {
|
||||
return false;
|
||||
}
|
||||
if (this.httpMethod != other.httpMethod) {
|
||||
return false;
|
||||
}
|
||||
if (!this.canonicalPath.equals(other.canonicalPath)) {
|
||||
return false;
|
||||
}
|
||||
if (!this.produces.equals(other.produces)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
boolean result = true;
|
||||
result = result && this.consumes.equals(other.consumes);
|
||||
result = result && this.httpMethod == other.httpMethod;
|
||||
result = result && this.canonicalPath.equals(other.canonicalPath);
|
||||
result = result && this.produces.equals(other.produces);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,11 +31,11 @@ import org.springframework.boot.endpoint.AnnotationEndpointDiscoverer;
|
|||
import org.springframework.boot.endpoint.CachingConfiguration;
|
||||
import org.springframework.boot.endpoint.CachingOperationInvoker;
|
||||
import org.springframework.boot.endpoint.Endpoint;
|
||||
import org.springframework.boot.endpoint.EndpointDelivery;
|
||||
import org.springframework.boot.endpoint.EndpointInfo;
|
||||
import org.springframework.boot.endpoint.EndpointOperationType;
|
||||
import org.springframework.boot.endpoint.EndpointType;
|
||||
import org.springframework.boot.endpoint.OperationInvoker;
|
||||
import org.springframework.boot.endpoint.OperationParameterMapper;
|
||||
import org.springframework.boot.endpoint.OperationType;
|
||||
import org.springframework.boot.endpoint.ReflectiveOperationInvoker;
|
||||
import org.springframework.boot.endpoint.Selector;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
|
@ -79,8 +79,8 @@ public class WebAnnotationEndpointDiscoverer extends
|
|||
|
||||
@Override
|
||||
public Collection<EndpointInfo<WebEndpointOperation>> discoverEndpoints() {
|
||||
Collection<EndpointInfoDescriptor<WebEndpointOperation, OperationRequestPredicate>> endpoints = discoverEndpointsWithExtension(
|
||||
WebEndpointExtension.class, EndpointType.WEB);
|
||||
Collection<EndpointInfoDescriptor<WebEndpointOperation, OperationRequestPredicate>> endpoints = discoverEndpoints(
|
||||
WebEndpointExtension.class, EndpointDelivery.WEB);
|
||||
verifyThatOperationsHaveDistinctPredicates(endpoints);
|
||||
return endpoints.stream().map(EndpointInfoDescriptor::getEndpointInfo)
|
||||
.collect(Collectors.toList());
|
||||
|
|
@ -129,7 +129,7 @@ public class WebAnnotationEndpointDiscoverer extends
|
|||
@Override
|
||||
public WebEndpointOperation createOperation(String endpointId,
|
||||
AnnotationAttributes operationAttributes, Object target, Method method,
|
||||
EndpointOperationType type, long timeToLive) {
|
||||
OperationType type, long timeToLive) {
|
||||
WebEndpointHttpMethod httpMethod = determineHttpMethod(type);
|
||||
OperationRequestPredicate requestPredicate = new OperationRequestPredicate(
|
||||
determinePath(endpointId, method), httpMethod,
|
||||
|
|
@ -201,9 +201,8 @@ public class WebAnnotationEndpointDiscoverer extends
|
|||
(parameter) -> parameter.getAnnotation(Selector.class) == null);
|
||||
}
|
||||
|
||||
private WebEndpointHttpMethod determineHttpMethod(
|
||||
EndpointOperationType operationType) {
|
||||
if (operationType == EndpointOperationType.WRITE) {
|
||||
private WebEndpointHttpMethod determineHttpMethod(OperationType operationType) {
|
||||
if (operationType == OperationType.WRITE) {
|
||||
return WebEndpointHttpMethod.POST;
|
||||
}
|
||||
return WebEndpointHttpMethod.GET;
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@
|
|||
|
||||
package org.springframework.boot.endpoint.web;
|
||||
|
||||
import org.springframework.boot.endpoint.EndpointOperation;
|
||||
import org.springframework.boot.endpoint.EndpointOperationType;
|
||||
import org.springframework.boot.endpoint.Operation;
|
||||
import org.springframework.boot.endpoint.OperationInvoker;
|
||||
import org.springframework.boot.endpoint.OperationType;
|
||||
|
||||
/**
|
||||
* An operation on a web endpoint.
|
||||
|
|
@ -26,7 +26,7 @@ import org.springframework.boot.endpoint.OperationInvoker;
|
|||
* @author Andy Wilkinson
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class WebEndpointOperation extends EndpointOperation {
|
||||
public class WebEndpointOperation extends Operation {
|
||||
|
||||
private final OperationRequestPredicate requestPredicate;
|
||||
|
||||
|
|
@ -42,9 +42,8 @@ public class WebEndpointOperation extends EndpointOperation {
|
|||
* @param requestPredicate the predicate for requests that can be handled by the
|
||||
* @param id the id of the operation, unique within its endpoint operation
|
||||
*/
|
||||
public WebEndpointOperation(EndpointOperationType type,
|
||||
OperationInvoker operationInvoker, boolean blocking,
|
||||
OperationRequestPredicate requestPredicate, String id) {
|
||||
public WebEndpointOperation(OperationType type, OperationInvoker operationInvoker,
|
||||
boolean blocking, OperationRequestPredicate requestPredicate, String id) {
|
||||
super(type, operationInvoker, blocking);
|
||||
this.requestPredicate = requestPredicate;
|
||||
this.id = id;
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ public class JerseyEndpointResourceFactory {
|
|||
resourceBuilder.addMethod(requestPredicate.getHttpMethod().name())
|
||||
.consumes(toStringArray(requestPredicate.getConsumes()))
|
||||
.produces(toStringArray(requestPredicate.getProduces()))
|
||||
.handledBy(new EndpointInvokingInflector(operation.getOperationInvoker(),
|
||||
.handledBy(new EndpointInvokingInflector(operation.getInvoker(),
|
||||
!requestPredicate.getConsumes().isEmpty()));
|
||||
return resourceBuilder.build();
|
||||
}
|
||||
|
|
@ -110,28 +110,32 @@ public class JerseyEndpointResourceFactory {
|
|||
this.readBody = readBody;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Response apply(ContainerRequestContext data) {
|
||||
Map<String, Object> arguments = new HashMap<>();
|
||||
if (this.readBody) {
|
||||
Map<String, Object> body = ((ContainerRequest) data)
|
||||
.readEntity(Map.class);
|
||||
if (body != null) {
|
||||
arguments.putAll(body);
|
||||
}
|
||||
arguments.putAll(extractBodyArguments(data));
|
||||
}
|
||||
arguments.putAll(extractPathParameters(data));
|
||||
arguments.putAll(extractQueryParameters(data));
|
||||
try {
|
||||
return convertToJaxRsResponse(this.operationInvoker.invoke(arguments),
|
||||
data.getRequest().getMethod());
|
||||
Object response = this.operationInvoker.invoke(arguments);
|
||||
return convertToJaxRsResponse(response, data.getRequest().getMethod());
|
||||
}
|
||||
catch (ParameterMappingException ex) {
|
||||
return Response.status(Status.BAD_REQUEST).build();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, Object> extractBodyArguments(ContainerRequestContext data) {
|
||||
Map<?, ?> entity = ((ContainerRequest) data).readEntity(Map.class);
|
||||
if (entity == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
return (Map<String, Object>) entity;
|
||||
}
|
||||
|
||||
private Map<String, Object> extractPathParameters(
|
||||
ContainerRequestContext requestContext) {
|
||||
return extract(requestContext.getUriInfo().getPathParameters());
|
||||
|
|
@ -155,8 +159,9 @@ public class JerseyEndpointResourceFactory {
|
|||
|
||||
private Response convertToJaxRsResponse(Object response, String httpMethod) {
|
||||
if (response == null) {
|
||||
return Response.status(HttpMethod.GET.equals(httpMethod)
|
||||
? Status.NOT_FOUND : Status.NO_CONTENT).build();
|
||||
boolean isGet = HttpMethod.GET.equals(httpMethod);
|
||||
Status status = (isGet ? Status.NOT_FOUND : Status.NO_CONTENT);
|
||||
return Response.status(status).build();
|
||||
}
|
||||
try {
|
||||
if (!(response instanceof WebEndpointResponse)) {
|
||||
|
|
|
|||
|
|
@ -47,8 +47,8 @@ import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMappi
|
|||
* @author Madhura Bhave
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public abstract class AbstractWebEndpointServletHandlerMapping extends RequestMappingInfoHandlerMapping
|
||||
implements InitializingBean {
|
||||
public abstract class AbstractWebEndpointServletHandlerMapping
|
||||
extends RequestMappingInfoHandlerMapping implements InitializingBean {
|
||||
|
||||
private final String endpointPath;
|
||||
|
||||
|
|
@ -96,9 +96,12 @@ public abstract class AbstractWebEndpointServletHandlerMapping extends RequestMa
|
|||
this.webEndpoints.stream()
|
||||
.flatMap((webEndpoint) -> webEndpoint.getOperations().stream())
|
||||
.forEach(this::registerMappingForOperation);
|
||||
registerMapping(new RequestMappingInfo(patternsRequestConditionForPattern(""),
|
||||
new RequestMethodsRequestCondition(RequestMethod.GET), null, null, null,
|
||||
null, null), this, getLinks());
|
||||
PatternsRequestCondition patterns = patternsRequestConditionForPattern("");
|
||||
RequestMethodsRequestCondition methods = new RequestMethodsRequestCondition(
|
||||
RequestMethod.GET);
|
||||
RequestMappingInfo mapping = new RequestMappingInfo(patterns, methods, null, null,
|
||||
null, null, null);
|
||||
registerMapping(mapping, this, getLinks());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -114,23 +117,22 @@ public abstract class AbstractWebEndpointServletHandlerMapping extends RequestMa
|
|||
protected RequestMappingInfo createRequestMappingInfo(
|
||||
WebEndpointOperation operationInfo) {
|
||||
OperationRequestPredicate requestPredicate = operationInfo.getRequestPredicate();
|
||||
return new RequestMappingInfo(null,
|
||||
patternsRequestConditionForPattern(requestPredicate.getPath()),
|
||||
new RequestMethodsRequestCondition(
|
||||
RequestMethod.valueOf(requestPredicate.getHttpMethod().name())),
|
||||
null, null,
|
||||
new ConsumesRequestCondition(
|
||||
toStringArray(requestPredicate.getConsumes())),
|
||||
new ProducesRequestCondition(
|
||||
toStringArray(requestPredicate.getProduces())),
|
||||
null);
|
||||
PatternsRequestCondition patterns = patternsRequestConditionForPattern(
|
||||
requestPredicate.getPath());
|
||||
RequestMethodsRequestCondition methods = new RequestMethodsRequestCondition(
|
||||
RequestMethod.valueOf(requestPredicate.getHttpMethod().name()));
|
||||
ConsumesRequestCondition consumes = new ConsumesRequestCondition(
|
||||
toStringArray(requestPredicate.getConsumes()));
|
||||
ProducesRequestCondition produces = new ProducesRequestCondition(
|
||||
toStringArray(requestPredicate.getProduces()));
|
||||
return new RequestMappingInfo(null, patterns, methods, null, null, consumes,
|
||||
produces, null);
|
||||
}
|
||||
|
||||
private PatternsRequestCondition patternsRequestConditionForPattern(String path) {
|
||||
return new PatternsRequestCondition(
|
||||
new String[] { this.endpointPath
|
||||
+ (StringUtils.hasText(path) ? "/" + path : "") },
|
||||
null, null, false, false);
|
||||
String[] patterns = new String[] {
|
||||
this.endpointPath + (StringUtils.hasText(path) ? "/" + path : "") };
|
||||
return new PatternsRequestCondition(patterns, null, null, false, false);
|
||||
}
|
||||
|
||||
private String[] toStringArray(Collection<String> collection) {
|
||||
|
|
@ -172,5 +174,4 @@ public abstract class AbstractWebEndpointServletHandlerMapping extends RequestMa
|
|||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,8 @@ import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMappi
|
|||
* @author Andy Wilkinson
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class WebEndpointServletHandlerMapping extends AbstractWebEndpointServletHandlerMapping {
|
||||
public class WebEndpointServletHandlerMapping
|
||||
extends AbstractWebEndpointServletHandlerMapping {
|
||||
|
||||
private final Method handle = ReflectionUtils.findMethod(OperationHandler.class,
|
||||
"handle", HttpServletRequest.class, Map.class);
|
||||
|
|
@ -84,11 +85,13 @@ public class WebEndpointServletHandlerMapping extends AbstractWebEndpointServlet
|
|||
setOrder(-100);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerMappingForOperation(WebEndpointOperation operation) {
|
||||
registerMapping(createRequestMappingInfo(operation),
|
||||
new OperationHandler(operation.getOperationInvoker()), this.handle);
|
||||
new OperationHandler(operation.getInvoker()), this.handle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Method getLinks() {
|
||||
return this.links;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ import java.util.Map;
|
|||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.boot.endpoint.EndpointInfo;
|
||||
import org.springframework.boot.endpoint.EndpointOperationType;
|
||||
import org.springframework.boot.endpoint.OperationInvoker;
|
||||
import org.springframework.boot.endpoint.OperationType;
|
||||
import org.springframework.boot.endpoint.ParameterMappingException;
|
||||
import org.springframework.boot.endpoint.web.EndpointLinksResolver;
|
||||
import org.springframework.boot.endpoint.web.Link;
|
||||
|
|
@ -126,29 +126,28 @@ public class WebEndpointReactiveHandlerMapping extends RequestMappingInfoHandler
|
|||
}
|
||||
|
||||
private void registerMappingForOperation(WebEndpointOperation operation) {
|
||||
EndpointOperationType operationType = operation.getType();
|
||||
OperationType operationType = operation.getType();
|
||||
registerMapping(createRequestMappingInfo(operation),
|
||||
operationType == EndpointOperationType.WRITE
|
||||
? new WriteOperationHandler(operation.getOperationInvoker())
|
||||
: new ReadOperationHandler(operation.getOperationInvoker()),
|
||||
operationType == EndpointOperationType.WRITE ? this.handleWrite
|
||||
operationType == OperationType.WRITE
|
||||
? new WriteOperationHandler(operation.getInvoker())
|
||||
: new ReadOperationHandler(operation.getInvoker()),
|
||||
operationType == OperationType.WRITE ? this.handleWrite
|
||||
: this.handleRead);
|
||||
}
|
||||
|
||||
private RequestMappingInfo createRequestMappingInfo(
|
||||
WebEndpointOperation operationInfo) {
|
||||
OperationRequestPredicate requestPredicate = operationInfo.getRequestPredicate();
|
||||
return new RequestMappingInfo(null,
|
||||
new PatternsRequestCondition(pathPatternParser
|
||||
.parse(this.endpointPath + "/" + requestPredicate.getPath())),
|
||||
new RequestMethodsRequestCondition(
|
||||
RequestMethod.valueOf(requestPredicate.getHttpMethod().name())),
|
||||
null, null,
|
||||
new ConsumesRequestCondition(
|
||||
toStringArray(requestPredicate.getConsumes())),
|
||||
new ProducesRequestCondition(
|
||||
toStringArray(requestPredicate.getProduces())),
|
||||
null);
|
||||
PatternsRequestCondition patterns = new PatternsRequestCondition(pathPatternParser
|
||||
.parse(this.endpointPath + "/" + requestPredicate.getPath()));
|
||||
RequestMethodsRequestCondition methods = new RequestMethodsRequestCondition(
|
||||
RequestMethod.valueOf(requestPredicate.getHttpMethod().name()));
|
||||
ConsumesRequestCondition consumes = new ConsumesRequestCondition(
|
||||
toStringArray(requestPredicate.getConsumes()));
|
||||
ProducesRequestCondition produces = new ProducesRequestCondition(
|
||||
toStringArray(requestPredicate.getProduces()));
|
||||
return new RequestMappingInfo(null, patterns, methods, null, null, consumes,
|
||||
produces, null);
|
||||
}
|
||||
|
||||
private String[] toStringArray(Collection<String> collection) {
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ public class AnnotationEndpointDiscovererTests {
|
|||
endpoints.get("test"));
|
||||
assertThat(operations).hasSize(3);
|
||||
operations.values()
|
||||
.forEach(operation -> assertThat(operation.getOperationInvoker())
|
||||
.forEach(operation -> assertThat(operation.getInvoker())
|
||||
.isNotInstanceOf(CachingOperationInvoker.class));
|
||||
});
|
||||
}
|
||||
|
|
@ -135,7 +135,7 @@ public class AnnotationEndpointDiscovererTests {
|
|||
endpoints.get("test"));
|
||||
assertThat(operations).hasSize(3);
|
||||
operations.values()
|
||||
.forEach(operation -> assertThat(operation.getOperationInvoker())
|
||||
.forEach(operation -> assertThat(operation.getInvoker())
|
||||
.isNotInstanceOf(CachingOperationInvoker.class));
|
||||
});
|
||||
}
|
||||
|
|
@ -154,16 +154,16 @@ public class AnnotationEndpointDiscovererTests {
|
|||
endpoints.get("test"));
|
||||
OperationInvoker getAllOperationInvoker = operations
|
||||
.get(ReflectionUtils.findMethod(TestEndpoint.class, "getAll"))
|
||||
.getOperationInvoker();
|
||||
.getInvoker();
|
||||
assertThat(getAllOperationInvoker)
|
||||
.isInstanceOf(CachingOperationInvoker.class);
|
||||
assertThat(((CachingOperationInvoker) getAllOperationInvoker).getTimeToLive())
|
||||
.isEqualTo(500);
|
||||
assertThat(operations.get(ReflectionUtils.findMethod(TestEndpoint.class,
|
||||
"getOne", String.class)).getOperationInvoker())
|
||||
"getOne", String.class)).getInvoker())
|
||||
.isNotInstanceOf(CachingOperationInvoker.class);
|
||||
assertThat(operations.get(ReflectionUtils.findMethod(TestEndpoint.class,
|
||||
"update", String.class, String.class)).getOperationInvoker())
|
||||
"update", String.class, String.class)).getInvoker())
|
||||
.isNotInstanceOf(CachingOperationInvoker.class);
|
||||
});
|
||||
}
|
||||
|
|
@ -186,7 +186,7 @@ public class AnnotationEndpointDiscovererTests {
|
|||
EndpointInfo<TestEndpointOperation> endpoint) {
|
||||
Map<Method, TestEndpointOperation> operationByMethod = new HashMap<>();
|
||||
endpoint.getOperations().forEach((operation) -> {
|
||||
EndpointOperation existing = operationByMethod
|
||||
Operation existing = operationByMethod
|
||||
.put(operation.getOperationMethod(), operation);
|
||||
if (existing != null) {
|
||||
throw new AssertionError(String.format(
|
||||
|
|
@ -281,11 +281,11 @@ public class AnnotationEndpointDiscovererTests {
|
|||
}
|
||||
}
|
||||
|
||||
private static final class TestEndpointOperation extends EndpointOperation {
|
||||
private static final class TestEndpointOperation extends Operation {
|
||||
|
||||
private final Method operationMethod;
|
||||
|
||||
private TestEndpointOperation(EndpointOperationType type,
|
||||
private TestEndpointOperation(OperationType type,
|
||||
OperationInvoker operationInvoker, Method operationMethod) {
|
||||
super(type, operationInvoker, true);
|
||||
this.operationMethod = operationMethod;
|
||||
|
|
@ -313,7 +313,7 @@ public class AnnotationEndpointDiscovererTests {
|
|||
|
||||
@Override
|
||||
public Collection<EndpointInfo<TestEndpointOperation>> discoverEndpoints() {
|
||||
return discoverEndpointsWithExtension(null, null).stream()
|
||||
return discoverEndpoints(null, null).stream()
|
||||
.map(EndpointInfoDescriptor::getEndpointInfo)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
|
@ -324,7 +324,7 @@ public class AnnotationEndpointDiscovererTests {
|
|||
@Override
|
||||
public TestEndpointOperation createOperation(String endpointId,
|
||||
AnnotationAttributes operationAttributes, Object target,
|
||||
Method operationMethod, EndpointOperationType operationType,
|
||||
Method operationMethod, OperationType operationType,
|
||||
long timeToLive) {
|
||||
return new TestEndpointOperation(operationType,
|
||||
createOperationInvoker(timeToLive), operationMethod);
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ import javax.management.MBeanParameterInfo;
|
|||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.endpoint.EndpointInfo;
|
||||
import org.springframework.boot.endpoint.EndpointOperationType;
|
||||
import org.springframework.boot.endpoint.OperationInvoker;
|
||||
import org.springframework.boot.endpoint.OperationType;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.entry;
|
||||
|
|
@ -44,9 +44,9 @@ public class EndpointMBeanInfoAssemblerTests {
|
|||
|
||||
@Test
|
||||
public void exposeSimpleReadOperation() {
|
||||
JmxEndpointOperation operation = new JmxEndpointOperation(
|
||||
EndpointOperationType.READ, new DummyOperationInvoker(), "getAll",
|
||||
Object.class, "Test operation", Collections.emptyList());
|
||||
JmxEndpointOperation operation = new JmxEndpointOperation(OperationType.READ,
|
||||
new DummyOperationInvoker(), "getAll", Object.class, "Test operation",
|
||||
Collections.emptyList());
|
||||
EndpointInfo<JmxEndpointOperation> endpoint = new EndpointInfo<>("test", true,
|
||||
Collections.singletonList(operation));
|
||||
EndpointMBeanInfo endpointMBeanInfo = this.mBeanInfoAssembler
|
||||
|
|
@ -73,9 +73,8 @@ public class EndpointMBeanInfoAssemblerTests {
|
|||
|
||||
@Test
|
||||
public void exposeSimpleWriteOperation() {
|
||||
JmxEndpointOperation operation = new JmxEndpointOperation(
|
||||
EndpointOperationType.WRITE, new DummyOperationInvoker(), "update",
|
||||
Object.class, "Update operation",
|
||||
JmxEndpointOperation operation = new JmxEndpointOperation(OperationType.WRITE,
|
||||
new DummyOperationInvoker(), "update", Object.class, "Update operation",
|
||||
Collections.singletonList(new JmxEndpointOperationParameterInfo("test",
|
||||
String.class, "Test argument")));
|
||||
EndpointInfo<JmxEndpointOperation> endpoint = new EndpointInfo<>("another", true,
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@ import org.springframework.boot.endpoint.CachingConfiguration;
|
|||
import org.springframework.boot.endpoint.CachingOperationInvoker;
|
||||
import org.springframework.boot.endpoint.ConversionServiceOperationParameterMapper;
|
||||
import org.springframework.boot.endpoint.Endpoint;
|
||||
import org.springframework.boot.endpoint.EndpointDelivery;
|
||||
import org.springframework.boot.endpoint.EndpointInfo;
|
||||
import org.springframework.boot.endpoint.EndpointType;
|
||||
import org.springframework.boot.endpoint.ReadOperation;
|
||||
import org.springframework.boot.endpoint.ReflectiveOperationInvoker;
|
||||
import org.springframework.boot.endpoint.WriteOperation;
|
||||
|
|
@ -77,7 +77,7 @@ public class JmxAnnotationEndpointDiscovererTests {
|
|||
.isEqualTo("Invoke getAll for endpoint test");
|
||||
assertThat(getAll.getOutputType()).isEqualTo(Object.class);
|
||||
assertThat(getAll.getParameters()).isEmpty();
|
||||
assertThat(getAll.getOperationInvoker())
|
||||
assertThat(getAll.getInvoker())
|
||||
.isInstanceOf(ReflectiveOperationInvoker.class);
|
||||
JmxEndpointOperation getSomething = operationByName.get("getSomething");
|
||||
assertThat(getSomething.getDescription())
|
||||
|
|
@ -155,10 +155,9 @@ public class JmxAnnotationEndpointDiscovererTests {
|
|||
assertThat(operationByName).containsOnlyKeys("getAll", "getSomething",
|
||||
"update");
|
||||
JmxEndpointOperation getAll = operationByName.get("getAll");
|
||||
assertThat(getAll.getOperationInvoker())
|
||||
.isInstanceOf(CachingOperationInvoker.class);
|
||||
assertThat(((CachingOperationInvoker) getAll.getOperationInvoker())
|
||||
.getTimeToLive()).isEqualTo(500);
|
||||
assertThat(getAll.getInvoker()).isInstanceOf(CachingOperationInvoker.class);
|
||||
assertThat(((CachingOperationInvoker) getAll.getInvoker()).getTimeToLive())
|
||||
.isEqualTo(500);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -174,16 +173,15 @@ public class JmxAnnotationEndpointDiscovererTests {
|
|||
assertThat(operationByName).containsOnlyKeys("getAll", "getSomething",
|
||||
"update", "getAnother");
|
||||
JmxEndpointOperation getAll = operationByName.get("getAll");
|
||||
assertThat(getAll.getOperationInvoker())
|
||||
assertThat(getAll.getInvoker())
|
||||
.isInstanceOf(CachingOperationInvoker.class);
|
||||
assertThat(((CachingOperationInvoker) getAll.getOperationInvoker())
|
||||
assertThat(((CachingOperationInvoker) getAll.getInvoker())
|
||||
.getTimeToLive()).isEqualTo(500);
|
||||
JmxEndpointOperation getAnother = operationByName.get("getAnother");
|
||||
assertThat(getAnother.getOperationInvoker())
|
||||
assertThat(getAnother.getInvoker())
|
||||
.isInstanceOf(CachingOperationInvoker.class);
|
||||
assertThat(
|
||||
((CachingOperationInvoker) getAnother.getOperationInvoker())
|
||||
.getTimeToLive()).isEqualTo(500);
|
||||
assertThat(((CachingOperationInvoker) getAnother.getInvoker())
|
||||
.getTimeToLive()).isEqualTo(500);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -333,7 +331,7 @@ public class JmxAnnotationEndpointDiscovererTests {
|
|||
|
||||
}
|
||||
|
||||
@Endpoint(id = "jmx", types = EndpointType.JMX)
|
||||
@Endpoint(id = "jmx", delivery = EndpointDelivery.JMX)
|
||||
private static class TestJmxEndpoint {
|
||||
|
||||
@ReadOperation
|
||||
|
|
@ -412,7 +410,7 @@ public class JmxAnnotationEndpointDiscovererTests {
|
|||
|
||||
}
|
||||
|
||||
@Endpoint(id = "nonjmx", types = EndpointType.WEB)
|
||||
@Endpoint(id = "nonjmx", delivery = EndpointDelivery.WEB)
|
||||
private static class NonJmxEndpoint {
|
||||
|
||||
@ReadOperation
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import org.assertj.core.api.Condition;
|
|||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.endpoint.EndpointInfo;
|
||||
import org.springframework.boot.endpoint.EndpointOperationType;
|
||||
import org.springframework.boot.endpoint.OperationType;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
|
@ -74,7 +74,7 @@ public class EndpointLinksResolverTests {
|
|||
}
|
||||
|
||||
private WebEndpointOperation operationWithPath(String path, String id) {
|
||||
return new WebEndpointOperation(EndpointOperationType.READ, null, false,
|
||||
return new WebEndpointOperation(OperationType.READ, null, false,
|
||||
new OperationRequestPredicate(path, WebEndpointHttpMethod.GET,
|
||||
Collections.emptyList(), Collections.emptyList()),
|
||||
id);
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ import org.springframework.boot.endpoint.CachingConfiguration;
|
|||
import org.springframework.boot.endpoint.CachingOperationInvoker;
|
||||
import org.springframework.boot.endpoint.ConversionServiceOperationParameterMapper;
|
||||
import org.springframework.boot.endpoint.Endpoint;
|
||||
import org.springframework.boot.endpoint.EndpointDelivery;
|
||||
import org.springframework.boot.endpoint.EndpointInfo;
|
||||
import org.springframework.boot.endpoint.EndpointType;
|
||||
import org.springframework.boot.endpoint.OperationInvoker;
|
||||
import org.springframework.boot.endpoint.ReadOperation;
|
||||
import org.springframework.boot.endpoint.Selector;
|
||||
|
|
@ -194,7 +194,7 @@ public class WebAnnotationEndpointDiscovererTests {
|
|||
EndpointInfo<WebEndpointOperation> endpoint = endpoints.get("test");
|
||||
assertThat(endpoint.getOperations()).hasSize(1);
|
||||
OperationInvoker operationInvoker = endpoint.getOperations()
|
||||
.iterator().next().getOperationInvoker();
|
||||
.iterator().next().getInvoker();
|
||||
assertThat(operationInvoker)
|
||||
.isInstanceOf(CachingOperationInvoker.class);
|
||||
assertThat(
|
||||
|
|
@ -375,7 +375,7 @@ public class WebAnnotationEndpointDiscovererTests {
|
|||
|
||||
}
|
||||
|
||||
@Endpoint(id = "nonweb", types = EndpointType.JMX)
|
||||
@Endpoint(id = "nonweb", delivery = EndpointDelivery.JMX)
|
||||
static class NonWebEndpoint {
|
||||
|
||||
@ReadOperation
|
||||
|
|
|
|||
Loading…
Reference in New Issue