commit
						3b49bdecb3
					
				| 
						 | 
					@ -40,19 +40,19 @@ public enum AccessLevel {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public static final String REQUEST_ATTRIBUTE = "cloudFoundryAccessLevel";
 | 
						public static final String REQUEST_ATTRIBUTE = "cloudFoundryAccessLevel";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final List<String> endpointIds;
 | 
						private final List<String> ids;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	AccessLevel(String... endpointIds) {
 | 
						AccessLevel(String... ids) {
 | 
				
			||||||
		this.endpointIds = Arrays.asList(endpointIds);
 | 
							this.ids = Arrays.asList(ids);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Returns if the access level should allow access to the specified endpoint path.
 | 
						 * Returns if the access level should allow access to the specified ID.
 | 
				
			||||||
	 * @param endpointId the endpoint ID to check
 | 
						 * @param id the ID to check
 | 
				
			||||||
	 * @return {@code true} if access is allowed
 | 
						 * @return {@code true} if access is allowed
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public boolean isAccessAllowed(String endpointId) {
 | 
						public boolean isAccessAllowed(String id) {
 | 
				
			||||||
		return this.endpointIds.isEmpty() || this.endpointIds.contains(endpointId);
 | 
							return this.ids.isEmpty() || this.ids.contains(id);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,7 +59,7 @@ class CloudFoundrySecurityInterceptor {
 | 
				
			||||||
		this.applicationId = applicationId;
 | 
							this.applicationId = applicationId;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Mono<SecurityResponse> preHandle(ServerWebExchange exchange, String endpointId) {
 | 
						Mono<SecurityResponse> preHandle(ServerWebExchange exchange, String id) {
 | 
				
			||||||
		ServerHttpRequest request = exchange.getRequest();
 | 
							ServerHttpRequest request = exchange.getRequest();
 | 
				
			||||||
		if (CorsUtils.isPreFlightRequest(request)) {
 | 
							if (CorsUtils.isPreFlightRequest(request)) {
 | 
				
			||||||
			return SUCCESS;
 | 
								return SUCCESS;
 | 
				
			||||||
| 
						 | 
					@ -72,7 +72,7 @@ class CloudFoundrySecurityInterceptor {
 | 
				
			||||||
			return Mono.error(new CloudFoundryAuthorizationException(
 | 
								return Mono.error(new CloudFoundryAuthorizationException(
 | 
				
			||||||
					Reason.SERVICE_UNAVAILABLE, "Cloud controller URL is not available"));
 | 
										Reason.SERVICE_UNAVAILABLE, "Cloud controller URL is not available"));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return check(exchange, endpointId).then(SUCCESS).doOnError(this::logError)
 | 
							return check(exchange, id).then(SUCCESS).doOnError(this::logError)
 | 
				
			||||||
				.onErrorResume(this::getErrorResponse);
 | 
									.onErrorResume(this::getErrorResponse);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -80,13 +80,13 @@ class CloudFoundrySecurityInterceptor {
 | 
				
			||||||
		logger.error(ex.getMessage(), ex);
 | 
							logger.error(ex.getMessage(), ex);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private Mono<Void> check(ServerWebExchange exchange, String path) {
 | 
						private Mono<Void> check(ServerWebExchange exchange, String id) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			Token token = getToken(exchange.getRequest());
 | 
								Token token = getToken(exchange.getRequest());
 | 
				
			||||||
			return this.tokenValidator.validate(token)
 | 
								return this.tokenValidator.validate(token)
 | 
				
			||||||
					.then(this.cloudFoundrySecurityService
 | 
										.then(this.cloudFoundrySecurityService
 | 
				
			||||||
							.getAccessLevel(token.toString(), this.applicationId))
 | 
												.getAccessLevel(token.toString(), this.applicationId))
 | 
				
			||||||
					.filter((accessLevel) -> accessLevel.isAccessAllowed(path))
 | 
										.filter((accessLevel) -> accessLevel.isAccessAllowed(id))
 | 
				
			||||||
					.switchIfEmpty(Mono.error(new CloudFoundryAuthorizationException(
 | 
										.switchIfEmpty(Mono.error(new CloudFoundryAuthorizationException(
 | 
				
			||||||
							Reason.ACCESS_DENIED, "Access denied")))
 | 
												Reason.ACCESS_DENIED, "Access denied")))
 | 
				
			||||||
					.doOnSuccess((accessLevel) -> exchange.getAttributes()
 | 
										.doOnSuccess((accessLevel) -> exchange.getAttributes()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,6 +27,7 @@ import reactor.core.publisher.Mono;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.AccessLevel;
 | 
					import org.springframework.boot.actuate.autoconfigure.cloudfoundry.AccessLevel;
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.SecurityResponse;
 | 
					import org.springframework.boot.actuate.autoconfigure.cloudfoundry.SecurityResponse;
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
 | 
					import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
 | 
					import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
 | 
					import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
 | 
				
			||||||
| 
						 | 
					@ -70,7 +71,7 @@ class CloudFoundryWebFluxEndpointHandlerMapping
 | 
				
			||||||
	protected ReactiveWebOperation wrapReactiveWebOperation(ExposableWebEndpoint endpoint,
 | 
						protected ReactiveWebOperation wrapReactiveWebOperation(ExposableWebEndpoint endpoint,
 | 
				
			||||||
			WebOperation operation, ReactiveWebOperation reactiveWebOperation) {
 | 
								WebOperation operation, ReactiveWebOperation reactiveWebOperation) {
 | 
				
			||||||
		return new SecureReactiveWebOperation(reactiveWebOperation,
 | 
							return new SecureReactiveWebOperation(reactiveWebOperation,
 | 
				
			||||||
				this.securityInterceptor, endpoint.getId());
 | 
									this.securityInterceptor, endpoint.getEndpointId());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
| 
						 | 
					@ -113,10 +114,11 @@ class CloudFoundryWebFluxEndpointHandlerMapping
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private final CloudFoundrySecurityInterceptor securityInterceptor;
 | 
							private final CloudFoundrySecurityInterceptor securityInterceptor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private final String endpointId;
 | 
							private final EndpointId endpointId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		SecureReactiveWebOperation(ReactiveWebOperation delegate,
 | 
							SecureReactiveWebOperation(ReactiveWebOperation delegate,
 | 
				
			||||||
				CloudFoundrySecurityInterceptor securityInterceptor, String endpointId) {
 | 
									CloudFoundrySecurityInterceptor securityInterceptor,
 | 
				
			||||||
 | 
									EndpointId endpointId) {
 | 
				
			||||||
			this.delegate = delegate;
 | 
								this.delegate = delegate;
 | 
				
			||||||
			this.securityInterceptor = securityInterceptor;
 | 
								this.securityInterceptor = securityInterceptor;
 | 
				
			||||||
			this.endpointId = endpointId;
 | 
								this.endpointId = endpointId;
 | 
				
			||||||
| 
						 | 
					@ -125,7 +127,8 @@ class CloudFoundryWebFluxEndpointHandlerMapping
 | 
				
			||||||
		@Override
 | 
							@Override
 | 
				
			||||||
		public Mono<ResponseEntity<Object>> handle(ServerWebExchange exchange,
 | 
							public Mono<ResponseEntity<Object>> handle(ServerWebExchange exchange,
 | 
				
			||||||
				Map<String, String> body) {
 | 
									Map<String, String> body) {
 | 
				
			||||||
			return this.securityInterceptor.preHandle(exchange, this.endpointId)
 | 
								return this.securityInterceptor
 | 
				
			||||||
 | 
										.preHandle(exchange, this.endpointId.toLowerCaseString())
 | 
				
			||||||
					.flatMap((securityResponse) -> flatMapResponse(exchange, body,
 | 
										.flatMap((securityResponse) -> flatMapResponse(exchange, body,
 | 
				
			||||||
							securityResponse));
 | 
												securityResponse));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,6 +28,7 @@ import org.springframework.boot.actuate.autoconfigure.cloudfoundry.CloudFoundryA
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.CloudFoundryAuthorizationException.Reason;
 | 
					import org.springframework.boot.actuate.autoconfigure.cloudfoundry.CloudFoundryAuthorizationException.Reason;
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.SecurityResponse;
 | 
					import org.springframework.boot.actuate.autoconfigure.cloudfoundry.SecurityResponse;
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.Token;
 | 
					import org.springframework.boot.actuate.autoconfigure.cloudfoundry.Token;
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.http.HttpMethod;
 | 
					import org.springframework.http.HttpMethod;
 | 
				
			||||||
import org.springframework.http.HttpStatus;
 | 
					import org.springframework.http.HttpStatus;
 | 
				
			||||||
import org.springframework.util.StringUtils;
 | 
					import org.springframework.util.StringUtils;
 | 
				
			||||||
| 
						 | 
					@ -59,7 +60,7 @@ class CloudFoundrySecurityInterceptor {
 | 
				
			||||||
		this.applicationId = applicationId;
 | 
							this.applicationId = applicationId;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SecurityResponse preHandle(HttpServletRequest request, String endpointId) {
 | 
						SecurityResponse preHandle(HttpServletRequest request, EndpointId endpointId) {
 | 
				
			||||||
		if (CorsUtils.isPreFlightRequest(request)) {
 | 
							if (CorsUtils.isPreFlightRequest(request)) {
 | 
				
			||||||
			return SecurityResponse.success();
 | 
								return SecurityResponse.success();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -90,12 +91,14 @@ class CloudFoundrySecurityInterceptor {
 | 
				
			||||||
		return SecurityResponse.success();
 | 
							return SecurityResponse.success();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private void check(HttpServletRequest request, String endpointId) throws Exception {
 | 
						private void check(HttpServletRequest request, EndpointId endpointId)
 | 
				
			||||||
 | 
								throws Exception {
 | 
				
			||||||
		Token token = getToken(request);
 | 
							Token token = getToken(request);
 | 
				
			||||||
		this.tokenValidator.validate(token);
 | 
							this.tokenValidator.validate(token);
 | 
				
			||||||
		AccessLevel accessLevel = this.cloudFoundrySecurityService
 | 
							AccessLevel accessLevel = this.cloudFoundrySecurityService
 | 
				
			||||||
				.getAccessLevel(token.toString(), this.applicationId);
 | 
									.getAccessLevel(token.toString(), this.applicationId);
 | 
				
			||||||
		if (!accessLevel.isAccessAllowed(endpointId)) {
 | 
							if (!accessLevel.isAccessAllowed(
 | 
				
			||||||
 | 
									(endpointId != null) ? endpointId.toLowerCaseString() : "")) {
 | 
				
			||||||
			throw new CloudFoundryAuthorizationException(Reason.ACCESS_DENIED,
 | 
								throw new CloudFoundryAuthorizationException(Reason.ACCESS_DENIED,
 | 
				
			||||||
					"Access denied");
 | 
										"Access denied");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,6 +27,7 @@ import javax.servlet.http.HttpServletResponse;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.AccessLevel;
 | 
					import org.springframework.boot.actuate.autoconfigure.cloudfoundry.AccessLevel;
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.SecurityResponse;
 | 
					import org.springframework.boot.actuate.autoconfigure.cloudfoundry.SecurityResponse;
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
 | 
					import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
 | 
					import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
 | 
					import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
 | 
				
			||||||
| 
						 | 
					@ -68,7 +69,7 @@ class CloudFoundryWebEndpointServletHandlerMapping
 | 
				
			||||||
	protected ServletWebOperation wrapServletWebOperation(ExposableWebEndpoint endpoint,
 | 
						protected ServletWebOperation wrapServletWebOperation(ExposableWebEndpoint endpoint,
 | 
				
			||||||
			WebOperation operation, ServletWebOperation servletWebOperation) {
 | 
								WebOperation operation, ServletWebOperation servletWebOperation) {
 | 
				
			||||||
		return new SecureServletWebOperation(servletWebOperation,
 | 
							return new SecureServletWebOperation(servletWebOperation,
 | 
				
			||||||
				this.securityInterceptor, endpoint.getId());
 | 
									this.securityInterceptor, endpoint.getEndpointId());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
| 
						 | 
					@ -76,7 +77,7 @@ class CloudFoundryWebEndpointServletHandlerMapping
 | 
				
			||||||
	protected Map<String, Map<String, Link>> links(HttpServletRequest request,
 | 
						protected Map<String, Map<String, Link>> links(HttpServletRequest request,
 | 
				
			||||||
			HttpServletResponse response) {
 | 
								HttpServletResponse response) {
 | 
				
			||||||
		SecurityResponse securityResponse = this.securityInterceptor.preHandle(request,
 | 
							SecurityResponse securityResponse = this.securityInterceptor.preHandle(request,
 | 
				
			||||||
				"");
 | 
									null);
 | 
				
			||||||
		if (!securityResponse.getStatus().equals(HttpStatus.OK)) {
 | 
							if (!securityResponse.getStatus().equals(HttpStatus.OK)) {
 | 
				
			||||||
			sendFailureResponse(response, securityResponse);
 | 
								sendFailureResponse(response, securityResponse);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -115,10 +116,11 @@ class CloudFoundryWebEndpointServletHandlerMapping
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private final CloudFoundrySecurityInterceptor securityInterceptor;
 | 
							private final CloudFoundrySecurityInterceptor securityInterceptor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private final String endpointId;
 | 
							private final EndpointId endpointId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		SecureServletWebOperation(ServletWebOperation delegate,
 | 
							SecureServletWebOperation(ServletWebOperation delegate,
 | 
				
			||||||
				CloudFoundrySecurityInterceptor securityInterceptor, String endpointId) {
 | 
									CloudFoundrySecurityInterceptor securityInterceptor,
 | 
				
			||||||
 | 
									EndpointId endpointId) {
 | 
				
			||||||
			this.delegate = delegate;
 | 
								this.delegate = delegate;
 | 
				
			||||||
			this.securityInterceptor = securityInterceptor;
 | 
								this.securityInterceptor = securityInterceptor;
 | 
				
			||||||
			this.endpointId = endpointId;
 | 
								this.endpointId = endpointId;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,7 @@ package org.springframework.boot.actuate.autoconfigure.endpoint;
 | 
				
			||||||
import java.time.Duration;
 | 
					import java.time.Duration;
 | 
				
			||||||
import java.util.function.Function;
 | 
					import java.util.function.Function;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.invoker.cache.CachingOperationInvokerAdvisor;
 | 
					import org.springframework.boot.actuate.endpoint.invoker.cache.CachingOperationInvokerAdvisor;
 | 
				
			||||||
import org.springframework.boot.context.properties.bind.BindResult;
 | 
					import org.springframework.boot.context.properties.bind.BindResult;
 | 
				
			||||||
import org.springframework.boot.context.properties.bind.Bindable;
 | 
					import org.springframework.boot.context.properties.bind.Bindable;
 | 
				
			||||||
| 
						 | 
					@ -33,7 +34,7 @@ import org.springframework.core.env.PropertyResolver;
 | 
				
			||||||
 * @author Stephane Nicoll
 | 
					 * @author Stephane Nicoll
 | 
				
			||||||
 * @author Phillip Webb
 | 
					 * @author Phillip Webb
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class EndpointIdTimeToLivePropertyFunction implements Function<String, Long> {
 | 
					class EndpointIdTimeToLivePropertyFunction implements Function<EndpointId, Long> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private static final Bindable<Duration> DURATION = Bindable.of(Duration.class);
 | 
						private static final Bindable<Duration> DURATION = Bindable.of(Duration.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,9 +49,9 @@ class EndpointIdTimeToLivePropertyFunction implements Function<String, Long> {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	public Long apply(String endpointId) {
 | 
						public Long apply(EndpointId endpointId) {
 | 
				
			||||||
		String name = String.format("management.endpoint.%s.cache.time-to-live",
 | 
							String name = String.format("management.endpoint.%s.cache.time-to-live",
 | 
				
			||||||
				endpointId);
 | 
									endpointId.toLowerCaseString());
 | 
				
			||||||
		BindResult<Duration> duration = Binder.get(this.environment).bind(name, DURATION);
 | 
							BindResult<Duration> duration = Binder.get(this.environment).bind(name, DURATION);
 | 
				
			||||||
		return duration.map(Duration::toMillis).orElse(null);
 | 
							return duration.map(Duration::toMillis).orElse(null);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,11 +21,13 @@ import java.util.Arrays;
 | 
				
			||||||
import java.util.Collection;
 | 
					import java.util.Collection;
 | 
				
			||||||
import java.util.Collections;
 | 
					import java.util.Collections;
 | 
				
			||||||
import java.util.HashSet;
 | 
					import java.util.HashSet;
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.Locale;
 | 
					import java.util.Locale;
 | 
				
			||||||
import java.util.Set;
 | 
					import java.util.Set;
 | 
				
			||||||
import java.util.stream.Collectors;
 | 
					import java.util.stream.Collectors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.EndpointFilter;
 | 
					import org.springframework.boot.actuate.endpoint.EndpointFilter;
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
				
			||||||
import org.springframework.boot.context.properties.bind.Bindable;
 | 
					import org.springframework.boot.context.properties.bind.Bindable;
 | 
				
			||||||
import org.springframework.boot.context.properties.bind.Binder;
 | 
					import org.springframework.boot.context.properties.bind.Binder;
 | 
				
			||||||
| 
						 | 
					@ -74,10 +76,19 @@ public class ExposeExcludePropertyEndpointFilter<E extends ExposableEndpoint<?>>
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private Set<String> bind(Binder binder, String name) {
 | 
						private Set<String> bind(Binder binder, String name) {
 | 
				
			||||||
		return asSet(binder.bind(name, Bindable.listOf(String.class))
 | 
							return asSet(binder.bind(name, Bindable.listOf(String.class)).map(this::cleanup)
 | 
				
			||||||
				.orElseGet(ArrayList::new));
 | 
									.orElseGet(ArrayList::new));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private List<String> cleanup(List<String> values) {
 | 
				
			||||||
 | 
							return values.stream().map(this::cleanup).collect(Collectors.toList());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private String cleanup(String value) {
 | 
				
			||||||
 | 
							return "*".equals(value) ? "*"
 | 
				
			||||||
 | 
									: EndpointId.fromPropertyValue(value).toLowerCaseString();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private Set<String> asSet(Collection<String> items) {
 | 
						private Set<String> asSet(Collection<String> items) {
 | 
				
			||||||
		if (items == null) {
 | 
							if (items == null) {
 | 
				
			||||||
			return Collections.emptySet();
 | 
								return Collections.emptySet();
 | 
				
			||||||
| 
						 | 
					@ -110,7 +121,7 @@ public class ExposeExcludePropertyEndpointFilter<E extends ExposableEndpoint<?>>
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private boolean contains(Set<String> items, ExposableEndpoint<?> endpoint) {
 | 
						private boolean contains(Set<String> items, ExposableEndpoint<?> endpoint) {
 | 
				
			||||||
		return items.contains(endpoint.getId().toLowerCase(Locale.ENGLISH));
 | 
							return items.contains(endpoint.getEndpointId().toLowerCaseString());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,7 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.condition;
 | 
				
			||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
import java.util.Optional;
 | 
					import java.util.Optional;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.EndpointExtension;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.EndpointExtension;
 | 
				
			||||||
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
 | 
					import org.springframework.boot.autoconfigure.condition.ConditionMessage;
 | 
				
			||||||
| 
						 | 
					@ -54,8 +55,8 @@ class OnEnabledEndpointCondition extends SpringBootCondition {
 | 
				
			||||||
			AnnotatedTypeMetadata metadata) {
 | 
								AnnotatedTypeMetadata metadata) {
 | 
				
			||||||
		Environment environment = context.getEnvironment();
 | 
							Environment environment = context.getEnvironment();
 | 
				
			||||||
		AnnotationAttributes attributes = getEndpointAttributes(context, metadata);
 | 
							AnnotationAttributes attributes = getEndpointAttributes(context, metadata);
 | 
				
			||||||
		String id = attributes.getString("id");
 | 
							EndpointId id = EndpointId.of(attributes.getString("id"));
 | 
				
			||||||
		String key = "management.endpoint." + id + ".enabled";
 | 
							String key = "management.endpoint." + id.toLowerCaseString() + ".enabled";
 | 
				
			||||||
		Boolean userDefinedEnabled = environment.getProperty(key, Boolean.class);
 | 
							Boolean userDefinedEnabled = environment.getProperty(key, Boolean.class);
 | 
				
			||||||
		if (userDefinedEnabled != null) {
 | 
							if (userDefinedEnabled != null) {
 | 
				
			||||||
			return new ConditionOutcome(userDefinedEnabled,
 | 
								return new ConditionOutcome(userDefinedEnabled,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,7 +52,8 @@ class DefaultEndpointObjectNameFactory implements EndpointObjectNameFactory {
 | 
				
			||||||
			throws MalformedObjectNameException {
 | 
								throws MalformedObjectNameException {
 | 
				
			||||||
		StringBuilder builder = new StringBuilder(this.properties.getDomain());
 | 
							StringBuilder builder = new StringBuilder(this.properties.getDomain());
 | 
				
			||||||
		builder.append(":type=Endpoint");
 | 
							builder.append(":type=Endpoint");
 | 
				
			||||||
		builder.append(",name=" + StringUtils.capitalize(endpoint.getId()));
 | 
							builder.append(
 | 
				
			||||||
 | 
									",name=" + StringUtils.capitalize(endpoint.getEndpointId().toString()));
 | 
				
			||||||
		String baseName = builder.toString();
 | 
							String baseName = builder.toString();
 | 
				
			||||||
		if (this.mBeanServer != null && hasMBean(baseName)) {
 | 
							if (this.mBeanServer != null && hasMBean(baseName)) {
 | 
				
			||||||
			builder.append(",context=" + this.contextId);
 | 
								builder.append(",context=" + this.contextId);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,8 +16,10 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package org.springframework.boot.actuate.autoconfigure.endpoint.web;
 | 
					package org.springframework.boot.actuate.autoconfigure.endpoint.web;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.HashMap;
 | 
				
			||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.web.PathMapper;
 | 
					import org.springframework.boot.actuate.endpoint.web.PathMapper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -28,15 +30,23 @@ import org.springframework.boot.actuate.endpoint.web.PathMapper;
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class MappingWebEndpointPathMapper implements PathMapper {
 | 
					class MappingWebEndpointPathMapper implements PathMapper {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final Map<String, String> pathMapping;
 | 
						private final Map<EndpointId, String> pathMapping;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	MappingWebEndpointPathMapper(Map<String, String> pathMapping) {
 | 
						MappingWebEndpointPathMapper(Map<String, String> pathMapping) {
 | 
				
			||||||
		this.pathMapping = pathMapping;
 | 
							this.pathMapping = new HashMap<>();
 | 
				
			||||||
 | 
							pathMapping.forEach((id, path) -> this.pathMapping
 | 
				
			||||||
 | 
									.put(EndpointId.fromPropertyValue(id), path));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
 | 
						@Deprecated
 | 
				
			||||||
	public String getRootPath(String endpointId) {
 | 
						public String getRootPath(String endpointId) {
 | 
				
			||||||
		return this.pathMapping.getOrDefault(endpointId, endpointId);
 | 
							return getRootPath(EndpointId.of(endpointId));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						public String getRootPath(EndpointId endpointId) {
 | 
				
			||||||
 | 
							return this.pathMapping.getOrDefault(endpointId, endpointId.toLowerCaseString());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,7 +28,7 @@ import org.slf4j.LoggerFactory;
 | 
				
			||||||
import org.springframework.util.Assert;
 | 
					import org.springframework.util.Assert;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * {@link MeterFilter} to log only once a warning message and deny {@link Meter.Id}.
 | 
					 * {@link MeterFilter} to log only once a warning message and deny {@code Meter.Id}.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author Jon Schneider
 | 
					 * @author Jon Schneider
 | 
				
			||||||
 * @author Dmytro Nosan
 | 
					 * @author Dmytro Nosan
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,6 +31,7 @@ import reactor.core.publisher.Mono;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
 | 
					import org.springframework.beans.factory.NoSuchBeanDefinitionException;
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
 | 
					import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints;
 | 
					import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints;
 | 
				
			||||||
import org.springframework.boot.security.reactive.ApplicationContextServerWebExchangeMatcher;
 | 
					import org.springframework.boot.security.reactive.ApplicationContextServerWebExchangeMatcher;
 | 
				
			||||||
| 
						 | 
					@ -208,9 +209,12 @@ public final class EndpointRequest {
 | 
				
			||||||
					.map(pathMappedEndpoints::getPath);
 | 
										.map(pathMappedEndpoints::getPath);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private String getEndpointId(Object source) {
 | 
							private EndpointId getEndpointId(Object source) {
 | 
				
			||||||
 | 
								if (source instanceof EndpointId) {
 | 
				
			||||||
 | 
									return (EndpointId) source;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			if (source instanceof String) {
 | 
								if (source instanceof String) {
 | 
				
			||||||
				return (String) source;
 | 
									return (EndpointId.of((String) source));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (source instanceof Class) {
 | 
								if (source instanceof Class) {
 | 
				
			||||||
				return getEndpointId((Class<?>) source);
 | 
									return getEndpointId((Class<?>) source);
 | 
				
			||||||
| 
						 | 
					@ -218,12 +222,12 @@ public final class EndpointRequest {
 | 
				
			||||||
			throw new IllegalStateException("Unsupported source " + source);
 | 
								throw new IllegalStateException("Unsupported source " + source);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private String getEndpointId(Class<?> source) {
 | 
							private EndpointId getEndpointId(Class<?> source) {
 | 
				
			||||||
			Endpoint annotation = AnnotatedElementUtils.getMergedAnnotation(source,
 | 
								Endpoint annotation = AnnotatedElementUtils.getMergedAnnotation(source,
 | 
				
			||||||
					Endpoint.class);
 | 
										Endpoint.class);
 | 
				
			||||||
			Assert.state(annotation != null,
 | 
								Assert.state(annotation != null,
 | 
				
			||||||
					() -> "Class " + source + " is not annotated with @Endpoint");
 | 
										() -> "Class " + source + " is not annotated with @Endpoint");
 | 
				
			||||||
			return annotation.id();
 | 
								return EndpointId.of(annotation.id());
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private List<ServerWebExchangeMatcher> getDelegateMatchers(Set<String> paths) {
 | 
							private List<ServerWebExchangeMatcher> getDelegateMatchers(Set<String> paths) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,6 +31,7 @@ import javax.servlet.http.HttpServletRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
 | 
					import org.springframework.beans.factory.NoSuchBeanDefinitionException;
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
 | 
					import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints;
 | 
					import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints;
 | 
				
			||||||
import org.springframework.boot.autoconfigure.security.servlet.RequestMatcherProvider;
 | 
					import org.springframework.boot.autoconfigure.security.servlet.RequestMatcherProvider;
 | 
				
			||||||
| 
						 | 
					@ -256,9 +257,12 @@ public final class EndpointRequest {
 | 
				
			||||||
					.map(pathMappedEndpoints::getPath);
 | 
										.map(pathMappedEndpoints::getPath);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private String getEndpointId(Object source) {
 | 
							private EndpointId getEndpointId(Object source) {
 | 
				
			||||||
 | 
								if (source instanceof EndpointId) {
 | 
				
			||||||
 | 
									return (EndpointId) source;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			if (source instanceof String) {
 | 
								if (source instanceof String) {
 | 
				
			||||||
				return (String) source;
 | 
									return (EndpointId.of((String) source));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (source instanceof Class) {
 | 
								if (source instanceof Class) {
 | 
				
			||||||
				return getEndpointId((Class<?>) source);
 | 
									return getEndpointId((Class<?>) source);
 | 
				
			||||||
| 
						 | 
					@ -266,12 +270,12 @@ public final class EndpointRequest {
 | 
				
			||||||
			throw new IllegalStateException("Unsupported source " + source);
 | 
								throw new IllegalStateException("Unsupported source " + source);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private String getEndpointId(Class<?> source) {
 | 
							private EndpointId getEndpointId(Class<?> source) {
 | 
				
			||||||
			Endpoint annotation = AnnotatedElementUtils.getMergedAnnotation(source,
 | 
								Endpoint annotation = AnnotatedElementUtils.getMergedAnnotation(source,
 | 
				
			||||||
					Endpoint.class);
 | 
										Endpoint.class);
 | 
				
			||||||
			Assert.state(annotation != null,
 | 
								Assert.state(annotation != null,
 | 
				
			||||||
					() -> "Class " + source + " is not annotated with @Endpoint");
 | 
										() -> "Class " + source + " is not annotated with @Endpoint");
 | 
				
			||||||
			return annotation.id();
 | 
								return EndpointId.of(annotation.id());
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private List<RequestMatcher> getDelegateMatchers(
 | 
							private List<RequestMatcher> getDelegateMatchers(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,7 @@ import java.util.function.Function;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.junit.Test;
 | 
					import org.junit.Test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.InvocationContext;
 | 
					import org.springframework.boot.actuate.endpoint.InvocationContext;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.SecurityContext;
 | 
					import org.springframework.boot.actuate.endpoint.SecurityContext;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
				
			||||||
| 
						 | 
					@ -57,7 +58,7 @@ public class CloudFoundryWebEndpointDiscovererTests {
 | 
				
			||||||
			Collection<ExposableWebEndpoint> endpoints = discoverer.getEndpoints();
 | 
								Collection<ExposableWebEndpoint> endpoints = discoverer.getEndpoints();
 | 
				
			||||||
			assertThat(endpoints.size()).isEqualTo(2);
 | 
								assertThat(endpoints.size()).isEqualTo(2);
 | 
				
			||||||
			for (ExposableWebEndpoint endpoint : endpoints) {
 | 
								for (ExposableWebEndpoint endpoint : endpoints) {
 | 
				
			||||||
				if (endpoint.getId().equals("health")) {
 | 
									if (endpoint.getEndpointId().equals(EndpointId.of("health"))) {
 | 
				
			||||||
					WebOperation operation = endpoint.getOperations().iterator().next();
 | 
										WebOperation operation = endpoint.getOperations().iterator().next();
 | 
				
			||||||
					assertThat(operation.invoke(new InvocationContext(
 | 
										assertThat(operation.invoke(new InvocationContext(
 | 
				
			||||||
							mock(SecurityContext.class), Collections.emptyMap())))
 | 
												mock(SecurityContext.class), Collections.emptyMap())))
 | 
				
			||||||
| 
						 | 
					@ -72,8 +73,8 @@ public class CloudFoundryWebEndpointDiscovererTests {
 | 
				
			||||||
		this.load((id) -> null, (id) -> id, configuration, consumer);
 | 
							this.load((id) -> null, (id) -> id, configuration, consumer);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private void load(Function<String, Long> timeToLive, PathMapper endpointPathMapper,
 | 
						private void load(Function<EndpointId, Long> timeToLive,
 | 
				
			||||||
			Class<?> configuration,
 | 
								PathMapper endpointPathMapper, Class<?> configuration,
 | 
				
			||||||
			Consumer<CloudFoundryWebEndpointDiscoverer> consumer) {
 | 
								Consumer<CloudFoundryWebEndpointDiscoverer> consumer) {
 | 
				
			||||||
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
 | 
							AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
 | 
				
			||||||
				configuration);
 | 
									configuration);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -167,13 +167,6 @@ public class CloudFoundryWebFluxEndpointIntegrationTests {
 | 
				
			||||||
				.jsonPath("_links.test-part").doesNotExist()));
 | 
									.jsonPath("_links.test-part").doesNotExist()));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private AnnotationConfigReactiveWebServerApplicationContext createApplicationContext(
 | 
					 | 
				
			||||||
			Class<?>... config) {
 | 
					 | 
				
			||||||
		AnnotationConfigReactiveWebServerApplicationContext context = new AnnotationConfigReactiveWebServerApplicationContext();
 | 
					 | 
				
			||||||
		context.register(config);
 | 
					 | 
				
			||||||
		return context;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	private ContextConsumer<AssertableReactiveWebApplicationContext> withWebTestClient(
 | 
						private ContextConsumer<AssertableReactiveWebApplicationContext> withWebTestClient(
 | 
				
			||||||
			Consumer<WebTestClient> clientConsumer) {
 | 
								Consumer<WebTestClient> clientConsumer) {
 | 
				
			||||||
		return (context) -> {
 | 
							return (context) -> {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,6 +33,7 @@ import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfi
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration;
 | 
					import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration;
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration;
 | 
					import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration;
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration;
 | 
					import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration;
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
 | 
				
			||||||
| 
						 | 
					@ -243,9 +244,10 @@ public class ReactiveCloudFoundryActuatorAutoConfigurationTests {
 | 
				
			||||||
							context);
 | 
												context);
 | 
				
			||||||
					Collection<ExposableWebEndpoint> endpoints = handlerMapping
 | 
										Collection<ExposableWebEndpoint> endpoints = handlerMapping
 | 
				
			||||||
							.getEndpoints();
 | 
												.getEndpoints();
 | 
				
			||||||
					List<String> endpointIds = endpoints.stream()
 | 
										List<EndpointId> endpointIds = endpoints.stream()
 | 
				
			||||||
							.map(ExposableEndpoint::getId).collect(Collectors.toList());
 | 
												.map(ExposableEndpoint::getEndpointId)
 | 
				
			||||||
					assertThat(endpointIds).contains("test");
 | 
												.collect(Collectors.toList());
 | 
				
			||||||
 | 
										assertThat(endpointIds).contains(EndpointId.of("test"));
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -261,7 +263,8 @@ public class ReactiveCloudFoundryActuatorAutoConfigurationTests {
 | 
				
			||||||
					Collection<ExposableWebEndpoint> endpoints = handlerMapping
 | 
										Collection<ExposableWebEndpoint> endpoints = handlerMapping
 | 
				
			||||||
							.getEndpoints();
 | 
												.getEndpoints();
 | 
				
			||||||
					ExposableWebEndpoint endpoint = endpoints.stream()
 | 
										ExposableWebEndpoint endpoint = endpoints.stream()
 | 
				
			||||||
							.filter((candidate) -> "test".equals(candidate.getId()))
 | 
												.filter((candidate) -> EndpointId.of("test")
 | 
				
			||||||
 | 
														.equals(candidate.getEndpointId()))
 | 
				
			||||||
							.findFirst().get();
 | 
												.findFirst().get();
 | 
				
			||||||
					assertThat(endpoint.getOperations()).hasSize(1);
 | 
										assertThat(endpoint.getOperations()).hasSize(1);
 | 
				
			||||||
					WebOperation operation = endpoint.getOperations().iterator().next();
 | 
										WebOperation operation = endpoint.getOperations().iterator().next();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,6 +26,7 @@ import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAu
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration;
 | 
					import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration;
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration;
 | 
					import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration;
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration;
 | 
					import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration;
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType;
 | 
					import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType;
 | 
				
			||||||
| 
						 | 
					@ -235,7 +236,8 @@ public class CloudFoundryActuatorAutoConfigurationTests {
 | 
				
			||||||
					Collection<ExposableWebEndpoint> endpoints = handlerMapping
 | 
										Collection<ExposableWebEndpoint> endpoints = handlerMapping
 | 
				
			||||||
							.getEndpoints();
 | 
												.getEndpoints();
 | 
				
			||||||
					assertThat(endpoints.stream()
 | 
										assertThat(endpoints.stream()
 | 
				
			||||||
							.filter((candidate) -> "test".equals(candidate.getId()))
 | 
												.filter((candidate) -> EndpointId.of("test")
 | 
				
			||||||
 | 
														.equals(candidate.getEndpointId()))
 | 
				
			||||||
							.findFirst()).isNotEmpty();
 | 
												.findFirst()).isNotEmpty();
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -253,7 +255,8 @@ public class CloudFoundryActuatorAutoConfigurationTests {
 | 
				
			||||||
					Collection<ExposableWebEndpoint> endpoints = handlerMapping
 | 
										Collection<ExposableWebEndpoint> endpoints = handlerMapping
 | 
				
			||||||
							.getEndpoints();
 | 
												.getEndpoints();
 | 
				
			||||||
					ExposableWebEndpoint endpoint = endpoints.stream()
 | 
										ExposableWebEndpoint endpoint = endpoints.stream()
 | 
				
			||||||
							.filter((candidate) -> "test".equals(candidate.getId()))
 | 
												.filter((candidate) -> EndpointId.of("test")
 | 
				
			||||||
 | 
														.equals(candidate.getEndpointId()))
 | 
				
			||||||
							.findFirst().get();
 | 
												.findFirst().get();
 | 
				
			||||||
					Collection<WebOperation> operations = endpoint.getOperations();
 | 
										Collection<WebOperation> operations = endpoint.getOperations();
 | 
				
			||||||
					assertThat(operations).hasSize(1);
 | 
										assertThat(operations).hasSize(1);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright 2012-2017 the original author or authors.
 | 
					 * Copyright 2012-2018 the original author or authors.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with the License.
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
| 
						 | 
					@ -26,6 +26,7 @@ import org.springframework.boot.actuate.autoconfigure.cloudfoundry.AccessLevel;
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.CloudFoundryAuthorizationException.Reason;
 | 
					import org.springframework.boot.actuate.autoconfigure.cloudfoundry.CloudFoundryAuthorizationException.Reason;
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.SecurityResponse;
 | 
					import org.springframework.boot.actuate.autoconfigure.cloudfoundry.SecurityResponse;
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.Token;
 | 
					import org.springframework.boot.actuate.autoconfigure.cloudfoundry.Token;
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.http.HttpHeaders;
 | 
					import org.springframework.http.HttpHeaders;
 | 
				
			||||||
import org.springframework.http.HttpStatus;
 | 
					import org.springframework.http.HttpStatus;
 | 
				
			||||||
import org.springframework.mock.web.MockHttpServletRequest;
 | 
					import org.springframework.mock.web.MockHttpServletRequest;
 | 
				
			||||||
| 
						 | 
					@ -65,13 +66,15 @@ public class CloudFoundrySecurityInterceptorTests {
 | 
				
			||||||
		this.request.setMethod("OPTIONS");
 | 
							this.request.setMethod("OPTIONS");
 | 
				
			||||||
		this.request.addHeader(HttpHeaders.ORIGIN, "http://example.com");
 | 
							this.request.addHeader(HttpHeaders.ORIGIN, "http://example.com");
 | 
				
			||||||
		this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
 | 
							this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
 | 
				
			||||||
		SecurityResponse response = this.interceptor.preHandle(this.request, "/a");
 | 
							SecurityResponse response = this.interceptor.preHandle(this.request,
 | 
				
			||||||
 | 
									EndpointId.of("test"));
 | 
				
			||||||
		assertThat(response.getStatus()).isEqualTo(HttpStatus.OK);
 | 
							assertThat(response.getStatus()).isEqualTo(HttpStatus.OK);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void preHandleWhenTokenIsMissingShouldReturnFalse() {
 | 
						public void preHandleWhenTokenIsMissingShouldReturnFalse() {
 | 
				
			||||||
		SecurityResponse response = this.interceptor.preHandle(this.request, "/a");
 | 
							SecurityResponse response = this.interceptor.preHandle(this.request,
 | 
				
			||||||
 | 
									EndpointId.of("test"));
 | 
				
			||||||
		assertThat(response.getStatus())
 | 
							assertThat(response.getStatus())
 | 
				
			||||||
				.isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus());
 | 
									.isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -79,7 +82,8 @@ public class CloudFoundrySecurityInterceptorTests {
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void preHandleWhenTokenIsNotBearerShouldReturnFalse() {
 | 
						public void preHandleWhenTokenIsNotBearerShouldReturnFalse() {
 | 
				
			||||||
		this.request.addHeader("Authorization", mockAccessToken());
 | 
							this.request.addHeader("Authorization", mockAccessToken());
 | 
				
			||||||
		SecurityResponse response = this.interceptor.preHandle(this.request, "/a");
 | 
							SecurityResponse response = this.interceptor.preHandle(this.request,
 | 
				
			||||||
 | 
									EndpointId.of("test"));
 | 
				
			||||||
		assertThat(response.getStatus())
 | 
							assertThat(response.getStatus())
 | 
				
			||||||
				.isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus());
 | 
									.isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -89,7 +93,8 @@ public class CloudFoundrySecurityInterceptorTests {
 | 
				
			||||||
		this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator,
 | 
							this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator,
 | 
				
			||||||
				this.securityService, null);
 | 
									this.securityService, null);
 | 
				
			||||||
		this.request.addHeader("Authorization", "bearer " + mockAccessToken());
 | 
							this.request.addHeader("Authorization", "bearer " + mockAccessToken());
 | 
				
			||||||
		SecurityResponse response = this.interceptor.preHandle(this.request, "/a");
 | 
							SecurityResponse response = this.interceptor.preHandle(this.request,
 | 
				
			||||||
 | 
									EndpointId.of("test"));
 | 
				
			||||||
		assertThat(response.getStatus())
 | 
							assertThat(response.getStatus())
 | 
				
			||||||
				.isEqualTo(Reason.SERVICE_UNAVAILABLE.getStatus());
 | 
									.isEqualTo(Reason.SERVICE_UNAVAILABLE.getStatus());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -99,7 +104,8 @@ public class CloudFoundrySecurityInterceptorTests {
 | 
				
			||||||
		this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, null,
 | 
							this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, null,
 | 
				
			||||||
				"my-app-id");
 | 
									"my-app-id");
 | 
				
			||||||
		this.request.addHeader("Authorization", "bearer " + mockAccessToken());
 | 
							this.request.addHeader("Authorization", "bearer " + mockAccessToken());
 | 
				
			||||||
		SecurityResponse response = this.interceptor.preHandle(this.request, "/a");
 | 
							SecurityResponse response = this.interceptor.preHandle(this.request,
 | 
				
			||||||
 | 
									EndpointId.of("test"));
 | 
				
			||||||
		assertThat(response.getStatus())
 | 
							assertThat(response.getStatus())
 | 
				
			||||||
				.isEqualTo(Reason.SERVICE_UNAVAILABLE.getStatus());
 | 
									.isEqualTo(Reason.SERVICE_UNAVAILABLE.getStatus());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -110,7 +116,8 @@ public class CloudFoundrySecurityInterceptorTests {
 | 
				
			||||||
		this.request.addHeader("Authorization", "bearer " + accessToken);
 | 
							this.request.addHeader("Authorization", "bearer " + accessToken);
 | 
				
			||||||
		given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
 | 
							given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
 | 
				
			||||||
				.willReturn(AccessLevel.RESTRICTED);
 | 
									.willReturn(AccessLevel.RESTRICTED);
 | 
				
			||||||
		SecurityResponse response = this.interceptor.preHandle(this.request, "/a");
 | 
							SecurityResponse response = this.interceptor.preHandle(this.request,
 | 
				
			||||||
 | 
									EndpointId.of("test"));
 | 
				
			||||||
		assertThat(response.getStatus()).isEqualTo(Reason.ACCESS_DENIED.getStatus());
 | 
							assertThat(response.getStatus()).isEqualTo(Reason.ACCESS_DENIED.getStatus());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -120,7 +127,8 @@ public class CloudFoundrySecurityInterceptorTests {
 | 
				
			||||||
		this.request.addHeader("Authorization", "Bearer " + accessToken);
 | 
							this.request.addHeader("Authorization", "Bearer " + accessToken);
 | 
				
			||||||
		given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
 | 
							given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
 | 
				
			||||||
				.willReturn(AccessLevel.FULL);
 | 
									.willReturn(AccessLevel.FULL);
 | 
				
			||||||
		SecurityResponse response = this.interceptor.preHandle(this.request, "/a");
 | 
							SecurityResponse response = this.interceptor.preHandle(this.request,
 | 
				
			||||||
 | 
									EndpointId.of("test"));
 | 
				
			||||||
		ArgumentCaptor<Token> tokenArgumentCaptor = ArgumentCaptor.forClass(Token.class);
 | 
							ArgumentCaptor<Token> tokenArgumentCaptor = ArgumentCaptor.forClass(Token.class);
 | 
				
			||||||
		verify(this.tokenValidator).validate(tokenArgumentCaptor.capture());
 | 
							verify(this.tokenValidator).validate(tokenArgumentCaptor.capture());
 | 
				
			||||||
		Token token = tokenArgumentCaptor.getValue();
 | 
							Token token = tokenArgumentCaptor.getValue();
 | 
				
			||||||
| 
						 | 
					@ -136,7 +144,8 @@ public class CloudFoundrySecurityInterceptorTests {
 | 
				
			||||||
		this.request.addHeader("Authorization", "Bearer " + accessToken);
 | 
							this.request.addHeader("Authorization", "Bearer " + accessToken);
 | 
				
			||||||
		given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
 | 
							given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
 | 
				
			||||||
				.willReturn(AccessLevel.RESTRICTED);
 | 
									.willReturn(AccessLevel.RESTRICTED);
 | 
				
			||||||
		SecurityResponse response = this.interceptor.preHandle(this.request, "info");
 | 
							SecurityResponse response = this.interceptor.preHandle(this.request,
 | 
				
			||||||
 | 
									EndpointId.of("info"));
 | 
				
			||||||
		ArgumentCaptor<Token> tokenArgumentCaptor = ArgumentCaptor.forClass(Token.class);
 | 
							ArgumentCaptor<Token> tokenArgumentCaptor = ArgumentCaptor.forClass(Token.class);
 | 
				
			||||||
		verify(this.tokenValidator).validate(tokenArgumentCaptor.capture());
 | 
							verify(this.tokenValidator).validate(tokenArgumentCaptor.capture());
 | 
				
			||||||
		Token token = tokenArgumentCaptor.getValue();
 | 
							Token token = tokenArgumentCaptor.getValue();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright 2012-2017 the original author or authors.
 | 
					 * Copyright 2012-2018 the original author or authors.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with the License.
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,7 @@ import java.util.function.Function;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.junit.Test;
 | 
					import org.junit.Test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.mock.env.MockEnvironment;
 | 
					import org.springframework.mock.env.MockEnvironment;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
					import static org.assertj.core.api.Assertions.assertThat;
 | 
				
			||||||
| 
						 | 
					@ -34,21 +35,26 @@ public class EndpointIdTimeToLivePropertyFunctionTests {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final MockEnvironment environment = new MockEnvironment();
 | 
						private final MockEnvironment environment = new MockEnvironment();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final Function<String, Long> timeToLive = new EndpointIdTimeToLivePropertyFunction(
 | 
						private final Function<EndpointId, Long> timeToLive = new EndpointIdTimeToLivePropertyFunction(
 | 
				
			||||||
			this.environment);
 | 
								this.environment);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void defaultConfiguration() {
 | 
						public void defaultConfiguration() {
 | 
				
			||||||
		Long result = this.timeToLive.apply("test");
 | 
							Long result = this.timeToLive.apply(EndpointId.of("test"));
 | 
				
			||||||
		assertThat(result).isNull();
 | 
							assertThat(result).isNull();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void userConfiguration() {
 | 
						public void userConfiguration() {
 | 
				
			||||||
		this.environment.setProperty("management.endpoint.test.cache.time-to-live",
 | 
							this.environment.setProperty(
 | 
				
			||||||
				"500");
 | 
									"management.endpoint.another-test.cache.time-to-live", "500");
 | 
				
			||||||
		Long result = this.timeToLive.apply("test");
 | 
							Long result = this.timeToLive.apply(EndpointId.of("anotherTest"));
 | 
				
			||||||
		assertThat(result).isEqualTo(500L);
 | 
							assertThat(result).isEqualTo(500L);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						public void mixedCaseUserConfiguration() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,7 @@ import org.junit.rules.ExpectedException;
 | 
				
			||||||
import org.mockito.MockitoAnnotations;
 | 
					import org.mockito.MockitoAnnotations;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.EndpointFilter;
 | 
					import org.springframework.boot.actuate.endpoint.EndpointFilter;
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
 | 
				
			||||||
import org.springframework.mock.env.MockEnvironment;
 | 
					import org.springframework.mock.env.MockEnvironment;
 | 
				
			||||||
| 
						 | 
					@ -81,43 +82,43 @@ public class ExposeExcludePropertyEndpointFilterTests {
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void matchWhenExposeIsEmptyAndExcludeIsEmptyAndInDefaultShouldMatch() {
 | 
						public void matchWhenExposeIsEmptyAndExcludeIsEmptyAndInDefaultShouldMatch() {
 | 
				
			||||||
		setupFilter("", "");
 | 
							setupFilter("", "");
 | 
				
			||||||
		assertThat(match("def")).isTrue();
 | 
							assertThat(match(EndpointId.of("def"))).isTrue();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void matchWhenExposeIsEmptyAndExcludeIsEmptyAndNotInDefaultShouldNotMatch() {
 | 
						public void matchWhenExposeIsEmptyAndExcludeIsEmptyAndNotInDefaultShouldNotMatch() {
 | 
				
			||||||
		setupFilter("", "");
 | 
							setupFilter("", "");
 | 
				
			||||||
		assertThat(match("bar")).isFalse();
 | 
							assertThat(match(EndpointId.of("bar"))).isFalse();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void matchWhenExposeMatchesAndExcludeIsEmptyShouldMatch() {
 | 
						public void matchWhenExposeMatchesAndExcludeIsEmptyShouldMatch() {
 | 
				
			||||||
		setupFilter("bar", "");
 | 
							setupFilter("bar", "");
 | 
				
			||||||
		assertThat(match("bar")).isTrue();
 | 
							assertThat(match(EndpointId.of("bar"))).isTrue();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void matchWhenExposeDoesNotMatchAndExcludeIsEmptyShouldNotMatch() {
 | 
						public void matchWhenExposeDoesNotMatchAndExcludeIsEmptyShouldNotMatch() {
 | 
				
			||||||
		setupFilter("bar", "");
 | 
							setupFilter("bar", "");
 | 
				
			||||||
		assertThat(match("baz")).isFalse();
 | 
							assertThat(match(EndpointId.of("baz"))).isFalse();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void matchWhenExposeMatchesAndExcludeMatchesShouldNotMatch() {
 | 
						public void matchWhenExposeMatchesAndExcludeMatchesShouldNotMatch() {
 | 
				
			||||||
		setupFilter("bar,baz", "baz");
 | 
							setupFilter("bar,baz", "baz");
 | 
				
			||||||
		assertThat(match("baz")).isFalse();
 | 
							assertThat(match(EndpointId.of("baz"))).isFalse();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void matchWhenExposeMatchesAndExcludeDoesNotMatchShouldMatch() {
 | 
						public void matchWhenExposeMatchesAndExcludeDoesNotMatchShouldMatch() {
 | 
				
			||||||
		setupFilter("bar,baz", "buz");
 | 
							setupFilter("bar,baz", "buz");
 | 
				
			||||||
		assertThat(match("baz")).isTrue();
 | 
							assertThat(match(EndpointId.of("baz"))).isTrue();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void matchWhenExposeMatchesWithDifferentCaseShouldMatch() {
 | 
						public void matchWhenExposeMatchesWithDifferentCaseShouldMatch() {
 | 
				
			||||||
		setupFilter("bar", "");
 | 
							setupFilter("bar", "");
 | 
				
			||||||
		assertThat(match("bAr")).isTrue();
 | 
							assertThat(match(EndpointId.of("bAr"))).isTrue();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
| 
						 | 
					@ -127,23 +128,29 @@ public class ExposeExcludePropertyEndpointFilterTests {
 | 
				
			||||||
		environment.setProperty("foo.exclude", "");
 | 
							environment.setProperty("foo.exclude", "");
 | 
				
			||||||
		this.filter = new ExposeExcludePropertyEndpointFilter<>(
 | 
							this.filter = new ExposeExcludePropertyEndpointFilter<>(
 | 
				
			||||||
				DifferentTestExposableWebEndpoint.class, environment, "foo");
 | 
									DifferentTestExposableWebEndpoint.class, environment, "foo");
 | 
				
			||||||
		assertThat(match("baz")).isTrue();
 | 
							assertThat(match(EndpointId.of("baz"))).isTrue();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void matchWhenIncludeIsAsteriskShouldMatchAll() {
 | 
						public void matchWhenIncludeIsAsteriskShouldMatchAll() {
 | 
				
			||||||
		setupFilter("*", "buz");
 | 
							setupFilter("*", "buz");
 | 
				
			||||||
		assertThat(match("bar")).isTrue();
 | 
							assertThat(match(EndpointId.of("bar"))).isTrue();
 | 
				
			||||||
		assertThat(match("baz")).isTrue();
 | 
							assertThat(match(EndpointId.of("baz"))).isTrue();
 | 
				
			||||||
		assertThat(match("buz")).isFalse();
 | 
							assertThat(match(EndpointId.of("buz"))).isFalse();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void matchWhenExcludeIsAsteriskShouldMatchNone() {
 | 
						public void matchWhenExcludeIsAsteriskShouldMatchNone() {
 | 
				
			||||||
		setupFilter("bar,baz,buz", "*");
 | 
							setupFilter("bar,baz,buz", "*");
 | 
				
			||||||
		assertThat(match("bar")).isFalse();
 | 
							assertThat(match(EndpointId.of("bar"))).isFalse();
 | 
				
			||||||
		assertThat(match("baz")).isFalse();
 | 
							assertThat(match(EndpointId.of("baz"))).isFalse();
 | 
				
			||||||
		assertThat(match("buz")).isFalse();
 | 
							assertThat(match(EndpointId.of("buz"))).isFalse();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						public void matchWhenMixedCaseShouldMatch() {
 | 
				
			||||||
 | 
							setupFilter("foo-bar", "");
 | 
				
			||||||
 | 
							assertThat(match(EndpointId.of("fooBar"))).isTrue();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private void setupFilter(String include, String exclude) {
 | 
						private void setupFilter(String include, String exclude) {
 | 
				
			||||||
| 
						 | 
					@ -155,9 +162,9 @@ public class ExposeExcludePropertyEndpointFilterTests {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@SuppressWarnings({ "rawtypes", "unchecked" })
 | 
						@SuppressWarnings({ "rawtypes", "unchecked" })
 | 
				
			||||||
	private boolean match(String id) {
 | 
						private boolean match(EndpointId id) {
 | 
				
			||||||
		ExposableEndpoint<?> endpoint = mock(TestExposableWebEndpoint.class);
 | 
							ExposableEndpoint<?> endpoint = mock(TestExposableWebEndpoint.class);
 | 
				
			||||||
		given(endpoint.getId()).willReturn(id);
 | 
							given(endpoint.getEndpointId()).willReturn(id);
 | 
				
			||||||
		return ((EndpointFilter) this.filter).match(endpoint);
 | 
							return ((EndpointFilter) this.filter).match(endpoint);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,6 +140,14 @@ public class ConditionalOnEnabledEndpointTests {
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						public void outcomeWhenEndpointEnabledPropertyIsTrueAndMixedCaseShouldMatch() {
 | 
				
			||||||
 | 
							this.contextRunner.withPropertyValues("management.endpoint.foo-bar.enabled=true")
 | 
				
			||||||
 | 
									.withUserConfiguration(
 | 
				
			||||||
 | 
											FooBarEndpointEnabledByDefaultFalseConfiguration.class)
 | 
				
			||||||
 | 
									.run((context) -> assertThat(context).hasBean("fooBar"));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Endpoint(id = "foo", enableByDefault = true)
 | 
						@Endpoint(id = "foo", enableByDefault = true)
 | 
				
			||||||
	static class FooEndpointEnabledByDefaultTrue {
 | 
						static class FooEndpointEnabledByDefaultTrue {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -150,6 +158,11 @@ public class ConditionalOnEnabledEndpointTests {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Endpoint(id = "fooBar", enableByDefault = false)
 | 
				
			||||||
 | 
						static class FooBarEndpointEnabledByDefaultFalse {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@EndpointExtension(endpoint = FooEndpointEnabledByDefaultTrue.class, filter = TestFilter.class)
 | 
						@EndpointExtension(endpoint = FooEndpointEnabledByDefaultTrue.class, filter = TestFilter.class)
 | 
				
			||||||
	static class FooEndpointExtensionEnabledByDefaultTrue {
 | 
						static class FooEndpointExtensionEnabledByDefaultTrue {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -191,6 +204,17 @@ public class ConditionalOnEnabledEndpointTests {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Configuration
 | 
				
			||||||
 | 
						static class FooBarEndpointEnabledByDefaultFalseConfiguration {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							@Bean
 | 
				
			||||||
 | 
							@ConditionalOnEnabledEndpoint
 | 
				
			||||||
 | 
							public FooBarEndpointEnabledByDefaultFalse fooBar() {
 | 
				
			||||||
 | 
								return new FooBarEndpointEnabledByDefaultFalse();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Configuration
 | 
						@Configuration
 | 
				
			||||||
	static class FooEndpointAndExtensionEnabledByDefaultTrueConfiguration {
 | 
						static class FooEndpointAndExtensionEnabledByDefaultTrueConfiguration {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,7 @@ import javax.management.ObjectName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.junit.Test;
 | 
					import org.junit.Test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.jmx.ExposableJmxEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.jmx.ExposableJmxEndpoint;
 | 
				
			||||||
import org.springframework.mock.env.MockEnvironment;
 | 
					import org.springframework.mock.env.MockEnvironment;
 | 
				
			||||||
import org.springframework.util.ObjectUtils;
 | 
					import org.springframework.util.ObjectUtils;
 | 
				
			||||||
| 
						 | 
					@ -50,22 +51,23 @@ public class DefaultEndpointObjectNameFactoryTests {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void generateObjectName() {
 | 
						public void generateObjectName() {
 | 
				
			||||||
		ObjectName objectName = generateObjectName(endpoint("Test"));
 | 
							ObjectName objectName = generateObjectName(endpoint(EndpointId.of("test")));
 | 
				
			||||||
		assertThat(objectName.toString())
 | 
							assertThat(objectName.toString())
 | 
				
			||||||
				.isEqualTo("org.springframework.boot:type=Endpoint,name=Test");
 | 
									.isEqualTo("org.springframework.boot:type=Endpoint,name=Test");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void generateObjectNameWithCapitalizedId() {
 | 
						public void generateObjectNameWithCapitalizedId() {
 | 
				
			||||||
		ObjectName objectName = generateObjectName(endpoint("test"));
 | 
							ObjectName objectName = generateObjectName(
 | 
				
			||||||
 | 
									endpoint(EndpointId.of("testEndpoint")));
 | 
				
			||||||
		assertThat(objectName.toString())
 | 
							assertThat(objectName.toString())
 | 
				
			||||||
				.isEqualTo("org.springframework.boot:type=Endpoint,name=Test");
 | 
									.isEqualTo("org.springframework.boot:type=Endpoint,name=TestEndpoint");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void generateObjectNameWithCustomDomain() {
 | 
						public void generateObjectNameWithCustomDomain() {
 | 
				
			||||||
		this.properties.setDomain("com.example.acme");
 | 
							this.properties.setDomain("com.example.acme");
 | 
				
			||||||
		ObjectName objectName = generateObjectName(endpoint("test"));
 | 
							ObjectName objectName = generateObjectName(endpoint(EndpointId.of("test")));
 | 
				
			||||||
		assertThat(objectName.toString())
 | 
							assertThat(objectName.toString())
 | 
				
			||||||
				.isEqualTo("com.example.acme:type=Endpoint,name=Test");
 | 
									.isEqualTo("com.example.acme:type=Endpoint,name=Test");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -73,7 +75,7 @@ public class DefaultEndpointObjectNameFactoryTests {
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void generateObjectNameWithUniqueNames() {
 | 
						public void generateObjectNameWithUniqueNames() {
 | 
				
			||||||
		this.properties.setUniqueNames(true);
 | 
							this.properties.setUniqueNames(true);
 | 
				
			||||||
		ExposableJmxEndpoint endpoint = endpoint("test");
 | 
							ExposableJmxEndpoint endpoint = endpoint(EndpointId.of("test"));
 | 
				
			||||||
		String id = ObjectUtils.getIdentityHexString(endpoint);
 | 
							String id = ObjectUtils.getIdentityHexString(endpoint);
 | 
				
			||||||
		ObjectName objectName = generateObjectName(endpoint);
 | 
							ObjectName objectName = generateObjectName(endpoint);
 | 
				
			||||||
		assertThat(objectName.toString()).isEqualTo(
 | 
							assertThat(objectName.toString()).isEqualTo(
 | 
				
			||||||
| 
						 | 
					@ -84,7 +86,7 @@ public class DefaultEndpointObjectNameFactoryTests {
 | 
				
			||||||
	public void generateObjectNameWithStaticNames() {
 | 
						public void generateObjectNameWithStaticNames() {
 | 
				
			||||||
		this.properties.getStaticNames().setProperty("counter", "42");
 | 
							this.properties.getStaticNames().setProperty("counter", "42");
 | 
				
			||||||
		this.properties.getStaticNames().setProperty("foo", "bar");
 | 
							this.properties.getStaticNames().setProperty("foo", "bar");
 | 
				
			||||||
		ObjectName objectName = generateObjectName(endpoint("test"));
 | 
							ObjectName objectName = generateObjectName(endpoint(EndpointId.of("test")));
 | 
				
			||||||
		assertThat(objectName.getKeyProperty("counter")).isEqualTo("42");
 | 
							assertThat(objectName.getKeyProperty("counter")).isEqualTo("42");
 | 
				
			||||||
		assertThat(objectName.getKeyProperty("foo")).isEqualTo("bar");
 | 
							assertThat(objectName.getKeyProperty("foo")).isEqualTo("bar");
 | 
				
			||||||
		assertThat(objectName.toString())
 | 
							assertThat(objectName.toString())
 | 
				
			||||||
| 
						 | 
					@ -99,7 +101,7 @@ public class DefaultEndpointObjectNameFactoryTests {
 | 
				
			||||||
				null)).willReturn(
 | 
									null)).willReturn(
 | 
				
			||||||
						Collections.singleton(new ObjectName(
 | 
											Collections.singleton(new ObjectName(
 | 
				
			||||||
								"org.springframework.boot:type=Endpoint,name=Test")));
 | 
													"org.springframework.boot:type=Endpoint,name=Test")));
 | 
				
			||||||
		ObjectName objectName = generateObjectName(endpoint("test"));
 | 
							ObjectName objectName = generateObjectName(endpoint(EndpointId.of("test")));
 | 
				
			||||||
		assertThat(objectName.toString()).isEqualTo(
 | 
							assertThat(objectName.toString()).isEqualTo(
 | 
				
			||||||
				"org.springframework.boot:type=Endpoint,name=Test,context=testContext");
 | 
									"org.springframework.boot:type=Endpoint,name=Test,context=testContext");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -115,9 +117,9 @@ public class DefaultEndpointObjectNameFactoryTests {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private ExposableJmxEndpoint endpoint(String id) {
 | 
						private ExposableJmxEndpoint endpoint(EndpointId id) {
 | 
				
			||||||
		ExposableJmxEndpoint endpoint = mock(ExposableJmxEndpoint.class);
 | 
							ExposableJmxEndpoint endpoint = mock(ExposableJmxEndpoint.class);
 | 
				
			||||||
		given(endpoint.getId()).willReturn(id);
 | 
							given(endpoint.getEndpointId()).willReturn(id);
 | 
				
			||||||
		return endpoint;
 | 
							return endpoint;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,8 @@ import java.util.Collections;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.junit.Test;
 | 
					import org.junit.Test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
					import static org.assertj.core.api.Assertions.assertThat;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -33,14 +35,29 @@ public class MappingWebEndpointPathMapperTests {
 | 
				
			||||||
	public void defaultConfiguration() {
 | 
						public void defaultConfiguration() {
 | 
				
			||||||
		MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
 | 
							MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
 | 
				
			||||||
				Collections.emptyMap());
 | 
									Collections.emptyMap());
 | 
				
			||||||
		assertThat(mapper.getRootPath("test")).isEqualTo("test");
 | 
							assertThat(mapper.getRootPath(EndpointId.of("test"))).isEqualTo("test");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void userConfiguration() {
 | 
						public void userConfiguration() {
 | 
				
			||||||
		MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
 | 
							MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
 | 
				
			||||||
				Collections.singletonMap("test", "custom"));
 | 
									Collections.singletonMap("test", "custom"));
 | 
				
			||||||
		assertThat(mapper.getRootPath("test")).isEqualTo("custom");
 | 
							assertThat(mapper.getRootPath(EndpointId.of("test"))).isEqualTo("custom");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						public void mixedCaseDefaultConfiguration() {
 | 
				
			||||||
 | 
							MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
 | 
				
			||||||
 | 
									Collections.emptyMap());
 | 
				
			||||||
 | 
							assertThat(mapper.getRootPath(EndpointId.of("testEndpoint")))
 | 
				
			||||||
 | 
									.isEqualTo("testendpoint");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						public void mixedCaseUserConfiguration() {
 | 
				
			||||||
 | 
							MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
 | 
				
			||||||
 | 
									Collections.singletonMap("test-endpoint", "custom"));
 | 
				
			||||||
 | 
							assertThat(mapper.getRootPath(EndpointId.of("testEndpoint"))).isEqualTo("custom");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,7 @@ import org.junit.Test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration;
 | 
					import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration;
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.endpoint.ExposeExcludePropertyEndpointFilter;
 | 
					import org.springframework.boot.actuate.autoconfigure.endpoint.ExposeExcludePropertyEndpointFilter;
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType;
 | 
					import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
 | 
					import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.web.PathMapper;
 | 
					import org.springframework.boot.actuate.endpoint.web.PathMapper;
 | 
				
			||||||
| 
						 | 
					@ -65,7 +66,7 @@ public class WebEndpointAutoConfigurationTests {
 | 
				
			||||||
				.run((context) -> {
 | 
									.run((context) -> {
 | 
				
			||||||
					assertThat(context).hasSingleBean(PathMapper.class);
 | 
										assertThat(context).hasSingleBean(PathMapper.class);
 | 
				
			||||||
					String pathMapping = context.getBean(PathMapper.class)
 | 
										String pathMapping = context.getBean(PathMapper.class)
 | 
				
			||||||
							.getRootPath("health");
 | 
												.getRootPath(EndpointId.of("health"));
 | 
				
			||||||
					assertThat(pathMapping).isEqualTo("healthcheck");
 | 
										assertThat(pathMapping).isEqualTo("healthcheck");
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,7 @@ import org.assertj.core.api.AssertDelegateTarget;
 | 
				
			||||||
import org.junit.Test;
 | 
					import org.junit.Test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
 | 
					import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.Operation;
 | 
					import org.springframework.boot.actuate.endpoint.Operation;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
				
			||||||
| 
						 | 
					@ -129,9 +130,9 @@ public class EndpointRequestTests {
 | 
				
			||||||
		ServerWebExchangeMatcher matcher = EndpointRequest.toAnyEndpoint()
 | 
							ServerWebExchangeMatcher matcher = EndpointRequest.toAnyEndpoint()
 | 
				
			||||||
				.excluding(FooEndpoint.class, BazServletEndpoint.class);
 | 
									.excluding(FooEndpoint.class, BazServletEndpoint.class);
 | 
				
			||||||
		List<ExposableEndpoint<?>> endpoints = new ArrayList<>();
 | 
							List<ExposableEndpoint<?>> endpoints = new ArrayList<>();
 | 
				
			||||||
		endpoints.add(mockEndpoint("foo", "foo"));
 | 
							endpoints.add(mockEndpoint(EndpointId.of("foo"), "foo"));
 | 
				
			||||||
		endpoints.add(mockEndpoint("bar", "bar"));
 | 
							endpoints.add(mockEndpoint(EndpointId.of("bar"), "bar"));
 | 
				
			||||||
		endpoints.add(mockEndpoint("baz", "baz"));
 | 
							endpoints.add(mockEndpoint(EndpointId.of("baz"), "baz"));
 | 
				
			||||||
		PathMappedEndpoints pathMappedEndpoints = new PathMappedEndpoints("/actuator",
 | 
							PathMappedEndpoints pathMappedEndpoints = new PathMappedEndpoints("/actuator",
 | 
				
			||||||
				() -> endpoints);
 | 
									() -> endpoints);
 | 
				
			||||||
		assertMatcher(matcher, pathMappedEndpoints).doesNotMatch("/actuator/foo");
 | 
							assertMatcher(matcher, pathMappedEndpoints).doesNotMatch("/actuator/foo");
 | 
				
			||||||
| 
						 | 
					@ -202,14 +203,14 @@ public class EndpointRequestTests {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private PathMappedEndpoints mockPathMappedEndpoints(String basePath) {
 | 
						private PathMappedEndpoints mockPathMappedEndpoints(String basePath) {
 | 
				
			||||||
		List<ExposableEndpoint<?>> endpoints = new ArrayList<>();
 | 
							List<ExposableEndpoint<?>> endpoints = new ArrayList<>();
 | 
				
			||||||
		endpoints.add(mockEndpoint("foo", "foo"));
 | 
							endpoints.add(mockEndpoint(EndpointId.of("foo"), "foo"));
 | 
				
			||||||
		endpoints.add(mockEndpoint("bar", "bar"));
 | 
							endpoints.add(mockEndpoint(EndpointId.of("bar"), "bar"));
 | 
				
			||||||
		return new PathMappedEndpoints(basePath, () -> endpoints);
 | 
							return new PathMappedEndpoints(basePath, () -> endpoints);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private TestEndpoint mockEndpoint(String id, String rootPath) {
 | 
						private TestEndpoint mockEndpoint(EndpointId id, String rootPath) {
 | 
				
			||||||
		TestEndpoint endpoint = mock(TestEndpoint.class);
 | 
							TestEndpoint endpoint = mock(TestEndpoint.class);
 | 
				
			||||||
		given(endpoint.getId()).willReturn(id);
 | 
							given(endpoint.getEndpointId()).willReturn(id);
 | 
				
			||||||
		given(endpoint.getRootPath()).willReturn(rootPath);
 | 
							given(endpoint.getRootPath()).willReturn(rootPath);
 | 
				
			||||||
		return endpoint;
 | 
							return endpoint;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,6 +25,7 @@ import org.assertj.core.api.AssertDelegateTarget;
 | 
				
			||||||
import org.junit.Test;
 | 
					import org.junit.Test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
 | 
					import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.Operation;
 | 
					import org.springframework.boot.actuate.endpoint.Operation;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
				
			||||||
| 
						 | 
					@ -163,9 +164,9 @@ public class EndpointRequestTests {
 | 
				
			||||||
		RequestMatcher matcher = EndpointRequest.toAnyEndpoint()
 | 
							RequestMatcher matcher = EndpointRequest.toAnyEndpoint()
 | 
				
			||||||
				.excluding(FooEndpoint.class, BazServletEndpoint.class);
 | 
									.excluding(FooEndpoint.class, BazServletEndpoint.class);
 | 
				
			||||||
		List<ExposableEndpoint<?>> endpoints = new ArrayList<>();
 | 
							List<ExposableEndpoint<?>> endpoints = new ArrayList<>();
 | 
				
			||||||
		endpoints.add(mockEndpoint("foo", "foo"));
 | 
							endpoints.add(mockEndpoint(EndpointId.of("foo"), "foo"));
 | 
				
			||||||
		endpoints.add(mockEndpoint("bar", "bar"));
 | 
							endpoints.add(mockEndpoint(EndpointId.of("bar"), "bar"));
 | 
				
			||||||
		endpoints.add(mockEndpoint("baz", "baz"));
 | 
							endpoints.add(mockEndpoint(EndpointId.of("baz"), "baz"));
 | 
				
			||||||
		PathMappedEndpoints pathMappedEndpoints = new PathMappedEndpoints("/actuator",
 | 
							PathMappedEndpoints pathMappedEndpoints = new PathMappedEndpoints("/actuator",
 | 
				
			||||||
				() -> endpoints);
 | 
									() -> endpoints);
 | 
				
			||||||
		assertMatcher(matcher, pathMappedEndpoints).doesNotMatch("/actuator/foo");
 | 
							assertMatcher(matcher, pathMappedEndpoints).doesNotMatch("/actuator/foo");
 | 
				
			||||||
| 
						 | 
					@ -258,14 +259,14 @@ public class EndpointRequestTests {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private PathMappedEndpoints mockPathMappedEndpoints(String basePath) {
 | 
						private PathMappedEndpoints mockPathMappedEndpoints(String basePath) {
 | 
				
			||||||
		List<ExposableEndpoint<?>> endpoints = new ArrayList<>();
 | 
							List<ExposableEndpoint<?>> endpoints = new ArrayList<>();
 | 
				
			||||||
		endpoints.add(mockEndpoint("foo", "foo"));
 | 
							endpoints.add(mockEndpoint(EndpointId.of("foo"), "foo"));
 | 
				
			||||||
		endpoints.add(mockEndpoint("bar", "bar"));
 | 
							endpoints.add(mockEndpoint(EndpointId.of("bar"), "bar"));
 | 
				
			||||||
		return new PathMappedEndpoints(basePath, () -> endpoints);
 | 
							return new PathMappedEndpoints(basePath, () -> endpoints);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private TestEndpoint mockEndpoint(String id, String rootPath) {
 | 
						private TestEndpoint mockEndpoint(EndpointId id, String rootPath) {
 | 
				
			||||||
		TestEndpoint endpoint = mock(TestEndpoint.class);
 | 
							TestEndpoint endpoint = mock(TestEndpoint.class);
 | 
				
			||||||
		given(endpoint.getId()).willReturn(id);
 | 
							given(endpoint.getEndpointId()).willReturn(id);
 | 
				
			||||||
		given(endpoint.getRootPath()).willReturn(rootPath);
 | 
							given(endpoint.getRootPath()).willReturn(rootPath);
 | 
				
			||||||
		return endpoint;
 | 
							return endpoint;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,7 +33,7 @@ import org.springframework.util.Assert;
 | 
				
			||||||
public abstract class AbstractExposableEndpoint<O extends Operation>
 | 
					public abstract class AbstractExposableEndpoint<O extends Operation>
 | 
				
			||||||
		implements ExposableEndpoint<O> {
 | 
							implements ExposableEndpoint<O> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final String id;
 | 
						private final EndpointId id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private boolean enabledByDefault;
 | 
						private boolean enabledByDefault;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,9 +44,24 @@ public abstract class AbstractExposableEndpoint<O extends Operation>
 | 
				
			||||||
	 * @param id the endpoint id
 | 
						 * @param id the endpoint id
 | 
				
			||||||
	 * @param enabledByDefault if the endpoint is enabled by default
 | 
						 * @param enabledByDefault if the endpoint is enabled by default
 | 
				
			||||||
	 * @param operations the endpoint operations
 | 
						 * @param operations the endpoint operations
 | 
				
			||||||
 | 
						 * @deprecated since 2.0.6 in favor of
 | 
				
			||||||
 | 
						 * {@link #AbstractExposableEndpoint(EndpointId, boolean, Collection)}
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
						@Deprecated
 | 
				
			||||||
	public AbstractExposableEndpoint(String id, boolean enabledByDefault,
 | 
						public AbstractExposableEndpoint(String id, boolean enabledByDefault,
 | 
				
			||||||
			Collection<? extends O> operations) {
 | 
								Collection<? extends O> operations) {
 | 
				
			||||||
 | 
							this(EndpointId.of(id), enabledByDefault, operations);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Create a new {@link AbstractExposableEndpoint} instance.
 | 
				
			||||||
 | 
						 * @param id the endpoint id
 | 
				
			||||||
 | 
						 * @param enabledByDefault if the endpoint is enabled by default
 | 
				
			||||||
 | 
						 * @param operations the endpoint operations
 | 
				
			||||||
 | 
						 * @since 2.0.6
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public AbstractExposableEndpoint(EndpointId id, boolean enabledByDefault,
 | 
				
			||||||
 | 
								Collection<? extends O> operations) {
 | 
				
			||||||
		Assert.notNull(id, "ID must not be null");
 | 
							Assert.notNull(id, "ID must not be null");
 | 
				
			||||||
		Assert.notNull(operations, "Operations must not be null");
 | 
							Assert.notNull(operations, "Operations must not be null");
 | 
				
			||||||
		this.id = id;
 | 
							this.id = id;
 | 
				
			||||||
| 
						 | 
					@ -56,7 +71,7 @@ public abstract class AbstractExposableEndpoint<O extends Operation>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	public String getId() {
 | 
						public String getId() {
 | 
				
			||||||
		return this.id;
 | 
							return this.id.toString();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,100 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright 2012-2018 the original author or authors.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package org.springframework.boot.actuate.endpoint;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Locale;
 | 
				
			||||||
 | 
					import java.util.regex.Pattern;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.util.Assert;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * An identifier for an actuator endpoint. Endpoint IDs may contain only letters and
 | 
				
			||||||
 | 
					 * numbers and must begin with a lower-case letter. Case is ignored when comparing
 | 
				
			||||||
 | 
					 * endpoint IDs.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @author Phillip Webb
 | 
				
			||||||
 | 
					 * @since 2.0.6
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public final class EndpointId {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private static final Pattern ALPHA_NUMERIC = Pattern.compile("[a-zA-Z0-9]+");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private final String value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private final String lowerCaseValue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private EndpointId(String value) {
 | 
				
			||||||
 | 
							Assert.hasText(value, "Value must not be empty");
 | 
				
			||||||
 | 
							Assert.isTrue(ALPHA_NUMERIC.matcher(value).matches(),
 | 
				
			||||||
 | 
									"Value must be alpha-numeric");
 | 
				
			||||||
 | 
							Assert.isTrue(!Character.isDigit(value.charAt(0)),
 | 
				
			||||||
 | 
									"Value must not start with a number");
 | 
				
			||||||
 | 
							Assert.isTrue(!Character.isUpperCase(value.charAt(0)),
 | 
				
			||||||
 | 
									"Value must not start with an uppercase letter");
 | 
				
			||||||
 | 
							this.value = value;
 | 
				
			||||||
 | 
							this.lowerCaseValue = value.toLowerCase(Locale.ENGLISH);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						public boolean equals(Object obj) {
 | 
				
			||||||
 | 
							if (this == obj) {
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (obj == null || getClass() != obj.getClass()) {
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return toLowerCaseString().equals(((EndpointId) obj).toLowerCaseString());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						public int hashCode() {
 | 
				
			||||||
 | 
							return toLowerCaseString().hashCode();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Return a lower-case version of the endpoint ID.
 | 
				
			||||||
 | 
						 * @return the lower-case endpoint ID
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public String toLowerCaseString() {
 | 
				
			||||||
 | 
							return this.lowerCaseValue;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						public String toString() {
 | 
				
			||||||
 | 
							return this.value;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Factory method to create a new {@link EndpointId} of the specified value.
 | 
				
			||||||
 | 
						 * @param value the endpoint ID value
 | 
				
			||||||
 | 
						 * @return an {@link EndpointId} instance
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public static EndpointId of(String value) {
 | 
				
			||||||
 | 
							return new EndpointId(value);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Factory method to create a new {@link EndpointId} from a property value. Is more
 | 
				
			||||||
 | 
						 * lenient that {@link #of(String)} to allow for common "relaxed" property variants.
 | 
				
			||||||
 | 
						 * @param value the property value to convert
 | 
				
			||||||
 | 
						 * @return an {@link EndpointId} instance
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public static EndpointId fromPropertyValue(String value) {
 | 
				
			||||||
 | 
							return new EndpointId(value.replace("-", ""));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -31,9 +31,20 @@ public interface ExposableEndpoint<O extends Operation> {
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Returns the id of the endpoint.
 | 
						 * Returns the id of the endpoint.
 | 
				
			||||||
	 * @return the id
 | 
						 * @return the id
 | 
				
			||||||
 | 
						 * @deprecated since 2.0.6 in favor of {@link #getEndpointId()}
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
						@Deprecated
 | 
				
			||||||
	String getId();
 | 
						String getId();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Return the endpoint ID.
 | 
				
			||||||
 | 
						 * @return the endpoint ID
 | 
				
			||||||
 | 
						 * @since 2.0.6
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						default EndpointId getEndpointId() {
 | 
				
			||||||
 | 
							return EndpointId.of(getId());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Returns if the endpoint is enabled by default.
 | 
						 * Returns if the endpoint is enabled by default.
 | 
				
			||||||
	 * @return if the endpoint is enabled by default
 | 
						 * @return if the endpoint is enabled by default
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,7 @@ package org.springframework.boot.actuate.endpoint.annotation;
 | 
				
			||||||
import java.util.Collection;
 | 
					import java.util.Collection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.AbstractExposableEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.AbstractExposableEndpoint;
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.Operation;
 | 
					import org.springframework.boot.actuate.endpoint.Operation;
 | 
				
			||||||
import org.springframework.core.style.ToStringCreator;
 | 
					import org.springframework.core.style.ToStringCreator;
 | 
				
			||||||
| 
						 | 
					@ -46,10 +47,28 @@ public abstract class AbstractDiscoveredEndpoint<O extends Operation>
 | 
				
			||||||
	 * @param id the ID of the endpoint
 | 
						 * @param id the ID of the endpoint
 | 
				
			||||||
	 * @param enabledByDefault if the endpoint is enabled by default
 | 
						 * @param enabledByDefault if the endpoint is enabled by default
 | 
				
			||||||
	 * @param operations the endpoint operations
 | 
						 * @param operations the endpoint operations
 | 
				
			||||||
 | 
						 * @deprecated since 2.0.6 in favor of
 | 
				
			||||||
 | 
						 * {@link #AbstractDiscoveredEndpoint(EndpointDiscoverer, Object, EndpointId, boolean, Collection)}
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
						@Deprecated
 | 
				
			||||||
	public AbstractDiscoveredEndpoint(EndpointDiscoverer<?, ?> discoverer,
 | 
						public AbstractDiscoveredEndpoint(EndpointDiscoverer<?, ?> discoverer,
 | 
				
			||||||
			Object endpointBean, String id, boolean enabledByDefault,
 | 
								Object endpointBean, String id, boolean enabledByDefault,
 | 
				
			||||||
			Collection<? extends O> operations) {
 | 
								Collection<? extends O> operations) {
 | 
				
			||||||
 | 
							this(discoverer, endpointBean, EndpointId.of(id), enabledByDefault, operations);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Create a new {@link AbstractDiscoveredEndpoint} instance.
 | 
				
			||||||
 | 
						 * @param discoverer the discoverer that discovered the endpoint
 | 
				
			||||||
 | 
						 * @param endpointBean the primary source bean
 | 
				
			||||||
 | 
						 * @param id the ID of the endpoint
 | 
				
			||||||
 | 
						 * @param enabledByDefault if the endpoint is enabled by default
 | 
				
			||||||
 | 
						 * @param operations the endpoint operations
 | 
				
			||||||
 | 
						 * @since 2.0.6
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public AbstractDiscoveredEndpoint(EndpointDiscoverer<?, ?> discoverer,
 | 
				
			||||||
 | 
								Object endpointBean, EndpointId id, boolean enabledByDefault,
 | 
				
			||||||
 | 
								Collection<? extends O> operations) {
 | 
				
			||||||
		super(id, enabledByDefault, operations);
 | 
							super(id, enabledByDefault, operations);
 | 
				
			||||||
		Assert.notNull(discoverer, "Discoverer must not be null");
 | 
							Assert.notNull(discoverer, "Discoverer must not be null");
 | 
				
			||||||
		Assert.notNull(endpointBean, "EndpointBean must not be null");
 | 
							Assert.notNull(endpointBean, "EndpointBean must not be null");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,7 @@ import java.util.EnumMap;
 | 
				
			||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
import java.util.Objects;
 | 
					import java.util.Objects;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.Operation;
 | 
					import org.springframework.boot.actuate.endpoint.Operation;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.OperationType;
 | 
					import org.springframework.boot.actuate.endpoint.OperationType;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.invoke.OperationInvoker;
 | 
					import org.springframework.boot.actuate.endpoint.invoke.OperationInvoker;
 | 
				
			||||||
| 
						 | 
					@ -68,20 +69,20 @@ abstract class DiscoveredOperationsFactory<O extends Operation> {
 | 
				
			||||||
		this.invokerAdvisors = invokerAdvisors;
 | 
							this.invokerAdvisors = invokerAdvisors;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public Collection<O> createOperations(String id, Object target) {
 | 
						public Collection<O> createOperations(EndpointId id, Object target) {
 | 
				
			||||||
		return MethodIntrospector.selectMethods(target.getClass(),
 | 
							return MethodIntrospector.selectMethods(target.getClass(),
 | 
				
			||||||
				(MetadataLookup<O>) (method) -> createOperation(id, target, method))
 | 
									(MetadataLookup<O>) (method) -> createOperation(id, target, method))
 | 
				
			||||||
				.values();
 | 
									.values();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private O createOperation(String endpointId, Object target, Method method) {
 | 
						private O createOperation(EndpointId endpointId, Object target, Method method) {
 | 
				
			||||||
		return OPERATION_TYPES.entrySet().stream()
 | 
							return OPERATION_TYPES.entrySet().stream()
 | 
				
			||||||
				.map((entry) -> createOperation(endpointId, target, method,
 | 
									.map((entry) -> createOperation(endpointId, target, method,
 | 
				
			||||||
						entry.getKey(), entry.getValue()))
 | 
											entry.getKey(), entry.getValue()))
 | 
				
			||||||
				.filter(Objects::nonNull).findFirst().orElse(null);
 | 
									.filter(Objects::nonNull).findFirst().orElse(null);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private O createOperation(String endpointId, Object target, Method method,
 | 
						private O createOperation(EndpointId endpointId, Object target, Method method,
 | 
				
			||||||
			OperationType operationType, Class<? extends Annotation> annotationType) {
 | 
								OperationType operationType, Class<? extends Annotation> annotationType) {
 | 
				
			||||||
		AnnotationAttributes annotationAttributes = AnnotatedElementUtils
 | 
							AnnotationAttributes annotationAttributes = AnnotatedElementUtils
 | 
				
			||||||
				.getMergedAnnotationAttributes(method, annotationType);
 | 
									.getMergedAnnotationAttributes(method, annotationType);
 | 
				
			||||||
| 
						 | 
					@ -96,7 +97,7 @@ abstract class DiscoveredOperationsFactory<O extends Operation> {
 | 
				
			||||||
		return createOperation(endpointId, operationMethod, invoker);
 | 
							return createOperation(endpointId, operationMethod, invoker);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private OperationInvoker applyAdvisors(String endpointId,
 | 
						private OperationInvoker applyAdvisors(EndpointId endpointId,
 | 
				
			||||||
			OperationMethod operationMethod, OperationInvoker invoker) {
 | 
								OperationMethod operationMethod, OperationInvoker invoker) {
 | 
				
			||||||
		if (this.invokerAdvisors != null) {
 | 
							if (this.invokerAdvisors != null) {
 | 
				
			||||||
			for (OperationInvokerAdvisor advisor : this.invokerAdvisors) {
 | 
								for (OperationInvokerAdvisor advisor : this.invokerAdvisors) {
 | 
				
			||||||
| 
						 | 
					@ -107,7 +108,7 @@ abstract class DiscoveredOperationsFactory<O extends Operation> {
 | 
				
			||||||
		return invoker;
 | 
							return invoker;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	protected abstract O createOperation(String endpointId,
 | 
						protected abstract O createOperation(EndpointId endpointId,
 | 
				
			||||||
			DiscoveredOperationMethod operationMethod, OperationInvoker invoker);
 | 
								DiscoveredOperationMethod operationMethod, OperationInvoker invoker);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,8 @@ import java.lang.annotation.Retention;
 | 
				
			||||||
import java.lang.annotation.RetentionPolicy;
 | 
					import java.lang.annotation.RetentionPolicy;
 | 
				
			||||||
import java.lang.annotation.Target;
 | 
					import java.lang.annotation.Target;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Identifies a type as being an actuator endpoint that provides information about the
 | 
					 * Identifies a type as being an actuator endpoint that provides information about the
 | 
				
			||||||
 * running application. Endpoints can be exposed over a variety of technologies including
 | 
					 * running application. Endpoints can be exposed over a variety of technologies including
 | 
				
			||||||
| 
						 | 
					@ -52,8 +54,9 @@ import java.lang.annotation.Target;
 | 
				
			||||||
public @interface Endpoint {
 | 
					public @interface Endpoint {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * The id of the endpoint.
 | 
						 * The id of the endpoint (must follow {@link EndpointId} rules).
 | 
				
			||||||
	 * @return the id
 | 
						 * @return the id
 | 
				
			||||||
 | 
						 * @see EndpointId
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	String id() default "";
 | 
						String id() default "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,6 +32,7 @@ import java.util.stream.Collectors;
 | 
				
			||||||
import org.springframework.beans.BeanUtils;
 | 
					import org.springframework.beans.BeanUtils;
 | 
				
			||||||
import org.springframework.beans.factory.BeanFactoryUtils;
 | 
					import org.springframework.beans.factory.BeanFactoryUtils;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.EndpointFilter;
 | 
					import org.springframework.boot.actuate.endpoint.EndpointFilter;
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.EndpointsSupplier;
 | 
					import org.springframework.boot.actuate.endpoint.EndpointsSupplier;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.Operation;
 | 
					import org.springframework.boot.actuate.endpoint.Operation;
 | 
				
			||||||
| 
						 | 
					@ -101,7 +102,7 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
 | 
				
			||||||
		return new DiscoveredOperationsFactory<O>(parameterValueMapper, invokerAdvisors) {
 | 
							return new DiscoveredOperationsFactory<O>(parameterValueMapper, invokerAdvisors) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			@Override
 | 
								@Override
 | 
				
			||||||
			protected O createOperation(String endpointId,
 | 
								protected O createOperation(EndpointId endpointId,
 | 
				
			||||||
					DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
 | 
										DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
 | 
				
			||||||
				return EndpointDiscoverer.this.createOperation(endpointId,
 | 
									return EndpointDiscoverer.this.createOperation(endpointId,
 | 
				
			||||||
						operationMethod, invoker);
 | 
											operationMethod, invoker);
 | 
				
			||||||
| 
						 | 
					@ -125,7 +126,7 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private Collection<EndpointBean> createEndpointBeans() {
 | 
						private Collection<EndpointBean> createEndpointBeans() {
 | 
				
			||||||
		Map<String, EndpointBean> byId = new LinkedHashMap<>();
 | 
							Map<EndpointId, EndpointBean> byId = new LinkedHashMap<>();
 | 
				
			||||||
		String[] beanNames = BeanFactoryUtils.beanNamesForAnnotationIncludingAncestors(
 | 
							String[] beanNames = BeanFactoryUtils.beanNamesForAnnotationIncludingAncestors(
 | 
				
			||||||
				this.applicationContext, Endpoint.class);
 | 
									this.applicationContext, Endpoint.class);
 | 
				
			||||||
		for (String beanName : beanNames) {
 | 
							for (String beanName : beanNames) {
 | 
				
			||||||
| 
						 | 
					@ -145,7 +146,7 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private void addExtensionBeans(Collection<EndpointBean> endpointBeans) {
 | 
						private void addExtensionBeans(Collection<EndpointBean> endpointBeans) {
 | 
				
			||||||
		Map<String, EndpointBean> byId = endpointBeans.stream()
 | 
							Map<EndpointId, EndpointBean> byId = endpointBeans.stream()
 | 
				
			||||||
				.collect(Collectors.toMap(EndpointBean::getId, (bean) -> bean));
 | 
									.collect(Collectors.toMap(EndpointBean::getId, (bean) -> bean));
 | 
				
			||||||
		String[] beanNames = BeanFactoryUtils.beanNamesForAnnotationIncludingAncestors(
 | 
							String[] beanNames = BeanFactoryUtils.beanNamesForAnnotationIncludingAncestors(
 | 
				
			||||||
				this.applicationContext, EndpointExtension.class);
 | 
									this.applicationContext, EndpointExtension.class);
 | 
				
			||||||
| 
						 | 
					@ -189,7 +190,7 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private E convertToEndpoint(EndpointBean endpointBean) {
 | 
						private E convertToEndpoint(EndpointBean endpointBean) {
 | 
				
			||||||
		MultiValueMap<OperationKey, O> indexed = new LinkedMultiValueMap<>();
 | 
							MultiValueMap<OperationKey, O> indexed = new LinkedMultiValueMap<>();
 | 
				
			||||||
		String id = endpointBean.getId();
 | 
							EndpointId id = endpointBean.getId();
 | 
				
			||||||
		addOperations(indexed, id, endpointBean.getBean(), false);
 | 
							addOperations(indexed, id, endpointBean.getBean(), false);
 | 
				
			||||||
		if (endpointBean.getExtensions().size() > 1) {
 | 
							if (endpointBean.getExtensions().size() > 1) {
 | 
				
			||||||
			String extensionBeans = endpointBean.getExtensions().stream()
 | 
								String extensionBeans = endpointBean.getExtensions().stream()
 | 
				
			||||||
| 
						 | 
					@ -209,7 +210,7 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
 | 
				
			||||||
				endpointBean.isEnabledByDefault(), operations);
 | 
									endpointBean.isEnabledByDefault(), operations);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private void addOperations(MultiValueMap<OperationKey, O> indexed, String id,
 | 
						private void addOperations(MultiValueMap<OperationKey, O> indexed, EndpointId id,
 | 
				
			||||||
			Object target, boolean replaceLast) {
 | 
								Object target, boolean replaceLast) {
 | 
				
			||||||
		Set<OperationKey> replacedLast = new HashSet<>();
 | 
							Set<OperationKey> replacedLast = new HashSet<>();
 | 
				
			||||||
		Collection<O> operations = this.operationsFactory.createOperations(id, target);
 | 
							Collection<O> operations = this.operationsFactory.createOperations(id, target);
 | 
				
			||||||
| 
						 | 
					@ -339,7 +340,25 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
 | 
				
			||||||
	 * @param enabledByDefault if the endpoint is enabled by default
 | 
						 * @param enabledByDefault if the endpoint is enabled by default
 | 
				
			||||||
	 * @param operations the endpoint operations
 | 
						 * @param operations the endpoint operations
 | 
				
			||||||
	 * @return a created endpoint (a {@link DiscoveredEndpoint} is recommended)
 | 
						 * @return a created endpoint (a {@link DiscoveredEndpoint} is recommended)
 | 
				
			||||||
 | 
						 * @since 2.0.6
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
						protected E createEndpoint(Object endpointBean, EndpointId id,
 | 
				
			||||||
 | 
								boolean enabledByDefault, Collection<O> operations) {
 | 
				
			||||||
 | 
							return createEndpoint(endpointBean, (id != null) ? id.toString() : null,
 | 
				
			||||||
 | 
									enabledByDefault, operations);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Factory method called to create the {@link ExposableEndpoint endpoint}.
 | 
				
			||||||
 | 
						 * @param endpointBean the source endpoint bean
 | 
				
			||||||
 | 
						 * @param id the ID of the endpoint
 | 
				
			||||||
 | 
						 * @param enabledByDefault if the endpoint is enabled by default
 | 
				
			||||||
 | 
						 * @param operations the endpoint operations
 | 
				
			||||||
 | 
						 * @return a created endpoint (a {@link DiscoveredEndpoint} is recommended)
 | 
				
			||||||
 | 
						 * @deprecated Since 2.0.6 in favor of
 | 
				
			||||||
 | 
						 * {@link #createEndpoint(Object, EndpointId, boolean, Collection)}
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						@Deprecated
 | 
				
			||||||
	protected abstract E createEndpoint(Object endpointBean, String id,
 | 
						protected abstract E createEndpoint(Object endpointBean, String id,
 | 
				
			||||||
			boolean enabledByDefault, Collection<O> operations);
 | 
								boolean enabledByDefault, Collection<O> operations);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -349,7 +368,24 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
 | 
				
			||||||
	 * @param operationMethod the operation method
 | 
						 * @param operationMethod the operation method
 | 
				
			||||||
	 * @param invoker the invoker to use
 | 
						 * @param invoker the invoker to use
 | 
				
			||||||
	 * @return a created operation
 | 
						 * @return a created operation
 | 
				
			||||||
 | 
						 * @since 2.0.6
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
						protected O createOperation(EndpointId endpointId,
 | 
				
			||||||
 | 
								DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
 | 
				
			||||||
 | 
							return createOperation((endpointId != null) ? endpointId.toString() : null,
 | 
				
			||||||
 | 
									operationMethod, invoker);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Factory method to create an {@link Operation endpoint operation}.
 | 
				
			||||||
 | 
						 * @param endpointId the endpoint id
 | 
				
			||||||
 | 
						 * @param operationMethod the operation method
 | 
				
			||||||
 | 
						 * @param invoker the invoker to use
 | 
				
			||||||
 | 
						 * @return a created operation
 | 
				
			||||||
 | 
						 * @deprecated since 2.0.6 in favor of
 | 
				
			||||||
 | 
						 * {@link #createOperation(EndpointId, DiscoveredOperationMethod, OperationInvoker)}
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						@Deprecated
 | 
				
			||||||
	protected abstract O createOperation(String endpointId,
 | 
						protected abstract O createOperation(String endpointId,
 | 
				
			||||||
			DiscoveredOperationMethod operationMethod, OperationInvoker invoker);
 | 
								DiscoveredOperationMethod operationMethod, OperationInvoker invoker);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -414,7 +450,7 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private final Object bean;
 | 
							private final Object bean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private final String id;
 | 
							private final EndpointId id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private boolean enabledByDefault;
 | 
							private boolean enabledByDefault;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -426,14 +462,15 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
 | 
				
			||||||
			AnnotationAttributes attributes = AnnotatedElementUtils
 | 
								AnnotationAttributes attributes = AnnotatedElementUtils
 | 
				
			||||||
					.findMergedAnnotationAttributes(bean.getClass(), Endpoint.class, true,
 | 
										.findMergedAnnotationAttributes(bean.getClass(), Endpoint.class, true,
 | 
				
			||||||
							true);
 | 
												true);
 | 
				
			||||||
			this.beanName = beanName;
 | 
								String id = attributes.getString("id");
 | 
				
			||||||
			this.bean = bean;
 | 
								Assert.state(StringUtils.hasText(id),
 | 
				
			||||||
			this.id = attributes.getString("id");
 | 
					 | 
				
			||||||
			this.enabledByDefault = (Boolean) attributes.get("enableByDefault");
 | 
					 | 
				
			||||||
			this.filter = getFilter(this.bean.getClass());
 | 
					 | 
				
			||||||
			Assert.state(StringUtils.hasText(this.id),
 | 
					 | 
				
			||||||
					() -> "No @Endpoint id attribute specified for "
 | 
										() -> "No @Endpoint id attribute specified for "
 | 
				
			||||||
							+ bean.getClass().getName());
 | 
												+ bean.getClass().getName());
 | 
				
			||||||
 | 
								this.beanName = beanName;
 | 
				
			||||||
 | 
								this.bean = bean;
 | 
				
			||||||
 | 
								this.id = EndpointId.of(id);
 | 
				
			||||||
 | 
								this.enabledByDefault = (Boolean) attributes.get("enableByDefault");
 | 
				
			||||||
 | 
								this.filter = getFilter(this.bean.getClass());
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public void addExtension(ExtensionBean extensionBean) {
 | 
							public void addExtension(ExtensionBean extensionBean) {
 | 
				
			||||||
| 
						 | 
					@ -461,7 +498,7 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
 | 
				
			||||||
			return this.bean;
 | 
								return this.bean;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public String getId() {
 | 
							public EndpointId getId() {
 | 
				
			||||||
			return this.id;
 | 
								return this.id;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -484,7 +521,7 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private final Object bean;
 | 
							private final Object bean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private final String endpointId;
 | 
							private final EndpointId endpointId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private final Class<?> filter;
 | 
							private final Class<?> filter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -500,7 +537,7 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
 | 
				
			||||||
							true);
 | 
												true);
 | 
				
			||||||
			Assert.state(endpointAttributes != null, () -> "Extension "
 | 
								Assert.state(endpointAttributes != null, () -> "Extension "
 | 
				
			||||||
					+ endpointType.getName() + " does not specify an endpoint");
 | 
										+ endpointType.getName() + " does not specify an endpoint");
 | 
				
			||||||
			this.endpointId = endpointAttributes.getString("id");
 | 
								this.endpointId = EndpointId.of(endpointAttributes.getString("id"));
 | 
				
			||||||
			this.filter = attributes.getClass("filter");
 | 
								this.filter = attributes.getClass("filter");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -512,7 +549,7 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
 | 
				
			||||||
			return this.bean;
 | 
								return this.bean;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public String getEndpointId() {
 | 
							public EndpointId getEndpointId() {
 | 
				
			||||||
			return this.endpointId;
 | 
								return this.endpointId;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package org.springframework.boot.actuate.endpoint.invoke;
 | 
					package org.springframework.boot.actuate.endpoint.invoke;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.OperationType;
 | 
					import org.springframework.boot.actuate.endpoint.OperationType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -34,7 +35,25 @@ public interface OperationInvokerAdvisor {
 | 
				
			||||||
	 * @param parameters the operation parameters
 | 
						 * @param parameters the operation parameters
 | 
				
			||||||
	 * @param invoker the invoker to advise
 | 
						 * @param invoker the invoker to advise
 | 
				
			||||||
	 * @return an potentially new operation invoker with support for additional features
 | 
						 * @return an potentially new operation invoker with support for additional features
 | 
				
			||||||
 | 
						 * @since 2.0.6
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
						default OperationInvoker apply(EndpointId endpointId, OperationType operationType,
 | 
				
			||||||
 | 
								OperationParameters parameters, OperationInvoker invoker) {
 | 
				
			||||||
 | 
							return apply((endpointId != null) ? endpointId.toString() : null, operationType,
 | 
				
			||||||
 | 
									parameters, invoker);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Apply additional functionality to the given invoker.
 | 
				
			||||||
 | 
						 * @param endpointId the endpoint ID
 | 
				
			||||||
 | 
						 * @param operationType the operation type
 | 
				
			||||||
 | 
						 * @param parameters the operation parameters
 | 
				
			||||||
 | 
						 * @param invoker the invoker to advise
 | 
				
			||||||
 | 
						 * @return an potentially new operation invoker with support for additional features
 | 
				
			||||||
 | 
						 * @deprecated since 2.0.6 in favor of
 | 
				
			||||||
 | 
						 * {@link #apply(EndpointId, OperationType, OperationParameters, OperationInvoker)}
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						@Deprecated
 | 
				
			||||||
	OperationInvoker apply(String endpointId, OperationType operationType,
 | 
						OperationInvoker apply(String endpointId, OperationType operationType,
 | 
				
			||||||
			OperationParameters parameters, OperationInvoker invoker);
 | 
								OperationParameters parameters, OperationInvoker invoker);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,7 @@ package org.springframework.boot.actuate.endpoint.invoker.cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.function.Function;
 | 
					import java.util.function.Function;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.OperationType;
 | 
					import org.springframework.boot.actuate.endpoint.OperationType;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.SecurityContext;
 | 
					import org.springframework.boot.actuate.endpoint.SecurityContext;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.invoke.OperationInvoker;
 | 
					import org.springframework.boot.actuate.endpoint.invoke.OperationInvoker;
 | 
				
			||||||
| 
						 | 
					@ -33,15 +34,23 @@ import org.springframework.boot.actuate.endpoint.invoke.OperationParameters;
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public class CachingOperationInvokerAdvisor implements OperationInvokerAdvisor {
 | 
					public class CachingOperationInvokerAdvisor implements OperationInvokerAdvisor {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final Function<String, Long> endpointIdTimeToLive;
 | 
						private final Function<EndpointId, Long> endpointIdTimeToLive;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public CachingOperationInvokerAdvisor(Function<String, Long> endpointIdTimeToLive) {
 | 
						public CachingOperationInvokerAdvisor(
 | 
				
			||||||
 | 
								Function<EndpointId, Long> endpointIdTimeToLive) {
 | 
				
			||||||
		this.endpointIdTimeToLive = endpointIdTimeToLive;
 | 
							this.endpointIdTimeToLive = endpointIdTimeToLive;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
 | 
						@Deprecated
 | 
				
			||||||
	public OperationInvoker apply(String endpointId, OperationType operationType,
 | 
						public OperationInvoker apply(String endpointId, OperationType operationType,
 | 
				
			||||||
			OperationParameters parameters, OperationInvoker invoker) {
 | 
								OperationParameters parameters, OperationInvoker invoker) {
 | 
				
			||||||
 | 
							return apply(EndpointId.of(endpointId), operationType, parameters, invoker);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						public OperationInvoker apply(EndpointId endpointId, OperationType operationType,
 | 
				
			||||||
 | 
								OperationParameters parameters, OperationInvoker invoker) {
 | 
				
			||||||
		if (operationType == OperationType.READ && !hasMandatoryParameter(parameters)) {
 | 
							if (operationType == OperationType.READ && !hasMandatoryParameter(parameters)) {
 | 
				
			||||||
			Long timeToLive = this.endpointIdTimeToLive.apply(endpointId);
 | 
								Long timeToLive = this.endpointIdTimeToLive.apply(endpointId);
 | 
				
			||||||
			if (timeToLive != null && timeToLive > 0) {
 | 
								if (timeToLive != null && timeToLive > 0) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -89,7 +89,7 @@ public class EndpointMBean implements DynamicMBean {
 | 
				
			||||||
			throws MBeanException, ReflectionException {
 | 
								throws MBeanException, ReflectionException {
 | 
				
			||||||
		JmxOperation operation = this.operations.get(actionName);
 | 
							JmxOperation operation = this.operations.get(actionName);
 | 
				
			||||||
		if (operation == null) {
 | 
							if (operation == null) {
 | 
				
			||||||
			String message = "Endpoint with id '" + this.endpoint.getId()
 | 
								String message = "Endpoint with id '" + this.endpoint.getEndpointId()
 | 
				
			||||||
					+ "' has no operation named " + actionName;
 | 
										+ "' has no operation named " + actionName;
 | 
				
			||||||
			throw new ReflectionException(new IllegalArgumentException(message), message);
 | 
								throw new ReflectionException(new IllegalArgumentException(message), message);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -136,7 +136,7 @@ public class JmxEndpointExporter
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private String getEndpointDescription(ExposableJmxEndpoint endpoint) {
 | 
						private String getEndpointDescription(ExposableJmxEndpoint endpoint) {
 | 
				
			||||||
		return "endpoint '" + endpoint.getId() + "'";
 | 
							return "endpoint '" + endpoint.getEndpointId() + "'";
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,7 +58,7 @@ class MBeanInfoFactory {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private String getDescription(ExposableJmxEndpoint endpoint) {
 | 
						private String getDescription(ExposableJmxEndpoint endpoint) {
 | 
				
			||||||
		return "MBean operations for endpoint " + endpoint.getId();
 | 
							return "MBean operations for endpoint " + endpoint.getEndpointId();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private ModelMBeanOperationInfo[] getMBeanOperations(ExposableJmxEndpoint endpoint) {
 | 
						private ModelMBeanOperationInfo[] getMBeanOperations(ExposableJmxEndpoint endpoint) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,7 @@ package org.springframework.boot.actuate.endpoint.jmx.annotation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.Collection;
 | 
					import java.util.Collection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredEndpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.jmx.ExposableJmxEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.jmx.ExposableJmxEndpoint;
 | 
				
			||||||
| 
						 | 
					@ -32,7 +33,8 @@ class DiscoveredJmxEndpoint extends AbstractDiscoveredEndpoint<JmxOperation>
 | 
				
			||||||
		implements ExposableJmxEndpoint {
 | 
							implements ExposableJmxEndpoint {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DiscoveredJmxEndpoint(EndpointDiscoverer<?, ?> discoverer, Object endpointBean,
 | 
						DiscoveredJmxEndpoint(EndpointDiscoverer<?, ?> discoverer, Object endpointBean,
 | 
				
			||||||
			String id, boolean enabledByDefault, Collection<JmxOperation> operations) {
 | 
								EndpointId id, boolean enabledByDefault,
 | 
				
			||||||
 | 
								Collection<JmxOperation> operations) {
 | 
				
			||||||
		super(discoverer, endpointBean, id, enabledByDefault, operations);
 | 
							super(discoverer, endpointBean, id, enabledByDefault, operations);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,6 +26,7 @@ import java.util.function.Supplier;
 | 
				
			||||||
import java.util.stream.Collectors;
 | 
					import java.util.stream.Collectors;
 | 
				
			||||||
import java.util.stream.Stream;
 | 
					import java.util.stream.Stream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredOperation;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredOperation;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.DiscoveredOperationMethod;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.DiscoveredOperationMethod;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.invoke.OperationInvoker;
 | 
					import org.springframework.boot.actuate.endpoint.invoke.OperationInvoker;
 | 
				
			||||||
| 
						 | 
					@ -59,8 +60,8 @@ class DiscoveredJmxOperation extends AbstractDiscoveredOperation implements JmxO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final List<JmxOperationParameter> parameters;
 | 
						private final List<JmxOperationParameter> parameters;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DiscoveredJmxOperation(String endpointId, DiscoveredOperationMethod operationMethod,
 | 
						DiscoveredJmxOperation(EndpointId endpointId,
 | 
				
			||||||
			OperationInvoker invoker) {
 | 
								DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
 | 
				
			||||||
		super(operationMethod, invoker);
 | 
							super(operationMethod, invoker);
 | 
				
			||||||
		Method method = operationMethod.getMethod();
 | 
							Method method = operationMethod.getMethod();
 | 
				
			||||||
		this.name = method.getName();
 | 
							this.name = method.getName();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,7 @@ package org.springframework.boot.actuate.endpoint.jmx.annotation;
 | 
				
			||||||
import java.util.Collection;
 | 
					import java.util.Collection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.EndpointFilter;
 | 
					import org.springframework.boot.actuate.endpoint.EndpointFilter;
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.DiscoveredOperationMethod;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.DiscoveredOperationMethod;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.invoke.OperationInvoker;
 | 
					import org.springframework.boot.actuate.endpoint.invoke.OperationInvoker;
 | 
				
			||||||
| 
						 | 
					@ -54,15 +55,30 @@ public class JmxEndpointDiscoverer
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
 | 
						@Deprecated
 | 
				
			||||||
	protected ExposableJmxEndpoint createEndpoint(Object endpointBean, String id,
 | 
						protected ExposableJmxEndpoint createEndpoint(Object endpointBean, String id,
 | 
				
			||||||
			boolean enabledByDefault, Collection<JmxOperation> operations) {
 | 
								boolean enabledByDefault, Collection<JmxOperation> operations) {
 | 
				
			||||||
 | 
							return createEndpoint(endpointBean, EndpointId.of(id), enabledByDefault,
 | 
				
			||||||
 | 
									operations);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						protected ExposableJmxEndpoint createEndpoint(Object endpointBean, EndpointId id,
 | 
				
			||||||
 | 
								boolean enabledByDefault, Collection<JmxOperation> operations) {
 | 
				
			||||||
		return new DiscoveredJmxEndpoint(this, endpointBean, id, enabledByDefault,
 | 
							return new DiscoveredJmxEndpoint(this, endpointBean, id, enabledByDefault,
 | 
				
			||||||
				operations);
 | 
									operations);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
 | 
						@Deprecated
 | 
				
			||||||
	protected JmxOperation createOperation(String endpointId,
 | 
						protected JmxOperation createOperation(String endpointId,
 | 
				
			||||||
			DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
 | 
								DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
 | 
				
			||||||
 | 
							return createOperation(EndpointId.of(endpointId), operationMethod, invoker);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						protected JmxOperation createOperation(EndpointId endpointId,
 | 
				
			||||||
 | 
								DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
 | 
				
			||||||
		return new DiscoveredJmxOperation(endpointId, operationMethod, invoker);
 | 
							return new DiscoveredJmxOperation(endpointId, operationMethod, invoker);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -76,8 +76,9 @@ public class EndpointLinksResolver {
 | 
				
			||||||
				collectLinks(links, (ExposableWebEndpoint) endpoint, normalizedUrl);
 | 
									collectLinks(links, (ExposableWebEndpoint) endpoint, normalizedUrl);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			else if (endpoint instanceof PathMappedEndpoint) {
 | 
								else if (endpoint instanceof PathMappedEndpoint) {
 | 
				
			||||||
				links.put(endpoint.getId(), createLink(normalizedUrl,
 | 
									String rootPath = ((PathMappedEndpoint) endpoint).getRootPath();
 | 
				
			||||||
						((PathMappedEndpoint) endpoint).getRootPath()));
 | 
									Link link = createLink(normalizedUrl, rootPath);
 | 
				
			||||||
 | 
									links.put(endpoint.getEndpointId().toLowerCaseString(), link);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return links;
 | 
							return links;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,6 +25,7 @@ import java.util.Map;
 | 
				
			||||||
import java.util.stream.Collectors;
 | 
					import java.util.stream.Collectors;
 | 
				
			||||||
import java.util.stream.Stream;
 | 
					import java.util.stream.Stream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.EndpointsSupplier;
 | 
					import org.springframework.boot.actuate.endpoint.EndpointsSupplier;
 | 
				
			||||||
import org.springframework.util.Assert;
 | 
					import org.springframework.util.Assert;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,7 +38,7 @@ public class PathMappedEndpoints implements Iterable<PathMappedEndpoint> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final String basePath;
 | 
						private final String basePath;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final Map<String, PathMappedEndpoint> endpoints;
 | 
						private final Map<EndpointId, PathMappedEndpoint> endpoints;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Create a new {@link PathMappedEndpoints} instance for the given supplier.
 | 
						 * Create a new {@link PathMappedEndpoints} instance for the given supplier.
 | 
				
			||||||
| 
						 | 
					@ -62,13 +63,14 @@ public class PathMappedEndpoints implements Iterable<PathMappedEndpoint> {
 | 
				
			||||||
		this.endpoints = getEndpoints(suppliers);
 | 
							this.endpoints = getEndpoints(suppliers);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private Map<String, PathMappedEndpoint> getEndpoints(
 | 
						private Map<EndpointId, PathMappedEndpoint> getEndpoints(
 | 
				
			||||||
			Collection<EndpointsSupplier<?>> suppliers) {
 | 
								Collection<EndpointsSupplier<?>> suppliers) {
 | 
				
			||||||
		Map<String, PathMappedEndpoint> endpoints = new LinkedHashMap<>();
 | 
							Map<EndpointId, PathMappedEndpoint> endpoints = new LinkedHashMap<>();
 | 
				
			||||||
		suppliers.forEach((supplier) -> {
 | 
							suppliers.forEach((supplier) -> {
 | 
				
			||||||
			supplier.getEndpoints().forEach((endpoint) -> {
 | 
								supplier.getEndpoints().forEach((endpoint) -> {
 | 
				
			||||||
				if (endpoint instanceof PathMappedEndpoint) {
 | 
									if (endpoint instanceof PathMappedEndpoint) {
 | 
				
			||||||
					endpoints.put(endpoint.getId(), (PathMappedEndpoint) endpoint);
 | 
										endpoints.put(endpoint.getEndpointId(),
 | 
				
			||||||
 | 
												(PathMappedEndpoint) endpoint);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
| 
						 | 
					@ -88,8 +90,21 @@ public class PathMappedEndpoints implements Iterable<PathMappedEndpoint> {
 | 
				
			||||||
	 * endpoint cannot be found.
 | 
						 * endpoint cannot be found.
 | 
				
			||||||
	 * @param endpointId the endpoint ID
 | 
						 * @param endpointId the endpoint ID
 | 
				
			||||||
	 * @return the root path or {@code null}
 | 
						 * @return the root path or {@code null}
 | 
				
			||||||
 | 
						 * @deprecated since 2.0.6 in favor of {@link #getRootPath(EndpointId)}
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
						@Deprecated
 | 
				
			||||||
	public String getRootPath(String endpointId) {
 | 
						public String getRootPath(String endpointId) {
 | 
				
			||||||
 | 
							return getRootPath(EndpointId.of(endpointId));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Return the root path for the endpoint with the given ID or {@code null} if the
 | 
				
			||||||
 | 
						 * endpoint cannot be found.
 | 
				
			||||||
 | 
						 * @param endpointId the endpoint ID
 | 
				
			||||||
 | 
						 * @return the root path or {@code null}
 | 
				
			||||||
 | 
						 * @since 2.0.6
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public String getRootPath(EndpointId endpointId) {
 | 
				
			||||||
		PathMappedEndpoint endpoint = getEndpoint(endpointId);
 | 
							PathMappedEndpoint endpoint = getEndpoint(endpointId);
 | 
				
			||||||
		return (endpoint != null) ? endpoint.getRootPath() : null;
 | 
							return (endpoint != null) ? endpoint.getRootPath() : null;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -99,8 +114,21 @@ public class PathMappedEndpoints implements Iterable<PathMappedEndpoint> {
 | 
				
			||||||
	 * endpoint cannot be found.
 | 
						 * endpoint cannot be found.
 | 
				
			||||||
	 * @param endpointId the endpoint ID
 | 
						 * @param endpointId the endpoint ID
 | 
				
			||||||
	 * @return the full path or {@code null}
 | 
						 * @return the full path or {@code null}
 | 
				
			||||||
 | 
						 * @deprecated since 2.0.6 in favor of {@link #getPath(EndpointId)}
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
						@Deprecated
 | 
				
			||||||
	public String getPath(String endpointId) {
 | 
						public String getPath(String endpointId) {
 | 
				
			||||||
 | 
							return getPath(EndpointId.of(endpointId));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Return the full path for the endpoint with the given ID or {@code null} if the
 | 
				
			||||||
 | 
						 * endpoint cannot be found.
 | 
				
			||||||
 | 
						 * @param endpointId the endpoint ID
 | 
				
			||||||
 | 
						 * @return the full path or {@code null}
 | 
				
			||||||
 | 
						 * @since 2.0.6
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public String getPath(EndpointId endpointId) {
 | 
				
			||||||
		return getPath(getEndpoint(endpointId));
 | 
							return getPath(getEndpoint(endpointId));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -125,8 +153,21 @@ public class PathMappedEndpoints implements Iterable<PathMappedEndpoint> {
 | 
				
			||||||
	 * endpoint cannot be found.
 | 
						 * endpoint cannot be found.
 | 
				
			||||||
	 * @param endpointId the endpoint ID
 | 
						 * @param endpointId the endpoint ID
 | 
				
			||||||
	 * @return the path mapped endpoint or {@code null}
 | 
						 * @return the path mapped endpoint or {@code null}
 | 
				
			||||||
 | 
						 * @deprecated since 2.0.6 in favor of {@link #getEndpoint(EndpointId)}
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
						@Deprecated
 | 
				
			||||||
	public PathMappedEndpoint getEndpoint(String endpointId) {
 | 
						public PathMappedEndpoint getEndpoint(String endpointId) {
 | 
				
			||||||
 | 
							return getEndpoint(EndpointId.of(endpointId));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Return the {@link PathMappedEndpoint} with the given ID or {@code null} if the
 | 
				
			||||||
 | 
						 * endpoint cannot be found.
 | 
				
			||||||
 | 
						 * @param endpointId the endpoint ID
 | 
				
			||||||
 | 
						 * @return the path mapped endpoint or {@code null}
 | 
				
			||||||
 | 
						 * @since 2.0.6
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public PathMappedEndpoint getEndpoint(EndpointId endpointId) {
 | 
				
			||||||
		return this.endpoints.get(endpointId);
 | 
							return this.endpoints.get(endpointId);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,8 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package org.springframework.boot.actuate.endpoint.web;
 | 
					package org.springframework.boot.actuate.endpoint.web;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Strategy interface used to provide a mapping between an endpoint ID and the root path
 | 
					 * Strategy interface used to provide a mapping between an endpoint ID and the root path
 | 
				
			||||||
 * where it will be exposed.
 | 
					 * where it will be exposed.
 | 
				
			||||||
| 
						 | 
					@ -31,15 +33,41 @@ public interface PathMapper {
 | 
				
			||||||
	 * Resolve the root path for the endpoint with the specified {@code endpointId}.
 | 
						 * Resolve the root path for the endpoint with the specified {@code endpointId}.
 | 
				
			||||||
	 * @param endpointId the id of an endpoint
 | 
						 * @param endpointId the id of an endpoint
 | 
				
			||||||
	 * @return the path of the endpoint
 | 
						 * @return the path of the endpoint
 | 
				
			||||||
 | 
						 * @since 2.0.6
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
						default String getRootPath(EndpointId endpointId) {
 | 
				
			||||||
 | 
							return getRootPath((endpointId != null) ? endpointId.toString() : null);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Resolve the root path for the endpoint with the specified {@code endpointId}.
 | 
				
			||||||
 | 
						 * @param endpointId the id of an endpoint
 | 
				
			||||||
 | 
						 * @return the path of the endpoint
 | 
				
			||||||
 | 
						 * @deprecated since 2.0.6 in favor of {@link #getRootPath(EndpointId)}
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						@Deprecated
 | 
				
			||||||
	String getRootPath(String endpointId);
 | 
						String getRootPath(String endpointId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Returns an {@link PathMapper} that uses the endpoint ID as the path.
 | 
						 * Returns an {@link PathMapper} that uses the endpoint ID as the path.
 | 
				
			||||||
	 * @return an {@link PathMapper} that uses the endpoint ID as the path
 | 
						 * @return an {@link PathMapper} that uses the lowercase endpoint ID as the path
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	static PathMapper useEndpointId() {
 | 
						static PathMapper useEndpointId() {
 | 
				
			||||||
		return (endpointId) -> endpointId;
 | 
							return new PathMapper() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								@Override
 | 
				
			||||||
 | 
								@Deprecated
 | 
				
			||||||
 | 
								public String getRootPath(String endpointId) {
 | 
				
			||||||
 | 
									return getRootPath(EndpointId.of(endpointId));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								@Override
 | 
				
			||||||
 | 
								public String getRootPath(EndpointId endpointId) {
 | 
				
			||||||
 | 
									return endpointId.toLowerCaseString();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,7 +67,7 @@ public class ServletEndpointRegistrar implements ServletContextInitializer {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private void register(ServletContext servletContext,
 | 
						private void register(ServletContext servletContext,
 | 
				
			||||||
			ExposableServletEndpoint endpoint) {
 | 
								ExposableServletEndpoint endpoint) {
 | 
				
			||||||
		String name = endpoint.getId() + "-actuator-endpoint";
 | 
							String name = endpoint.getEndpointId().toLowerCaseString() + "-actuator-endpoint";
 | 
				
			||||||
		String path = this.basePath + "/" + endpoint.getRootPath();
 | 
							String path = this.basePath + "/" + endpoint.getRootPath();
 | 
				
			||||||
		String urlMapping = path.endsWith("/") ? path + "*" : path + "/*";
 | 
							String urlMapping = path.endsWith("/") ? path + "*" : path + "/*";
 | 
				
			||||||
		EndpointServlet endpointServlet = endpoint.getEndpointServlet();
 | 
							EndpointServlet endpointServlet = endpoint.getEndpointServlet();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,7 @@ import java.util.Collection;
 | 
				
			||||||
import java.util.Collections;
 | 
					import java.util.Collections;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.EndpointFilter;
 | 
					import org.springframework.boot.actuate.endpoint.EndpointFilter;
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.Operation;
 | 
					import org.springframework.boot.actuate.endpoint.Operation;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.DiscoveredOperationMethod;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.DiscoveredOperationMethod;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer;
 | 
				
			||||||
| 
						 | 
					@ -67,16 +68,31 @@ public class ControllerEndpointDiscoverer
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
 | 
						@Deprecated
 | 
				
			||||||
	protected ExposableControllerEndpoint createEndpoint(Object endpointBean, String id,
 | 
						protected ExposableControllerEndpoint createEndpoint(Object endpointBean, String id,
 | 
				
			||||||
			boolean enabledByDefault, Collection<Operation> operations) {
 | 
								boolean enabledByDefault, Collection<Operation> operations) {
 | 
				
			||||||
 | 
							return createEndpoint(endpointBean, (id != null) ? EndpointId.of(id) : null,
 | 
				
			||||||
 | 
									enabledByDefault, operations);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						protected ExposableControllerEndpoint createEndpoint(Object endpointBean,
 | 
				
			||||||
 | 
								EndpointId id, boolean enabledByDefault, Collection<Operation> operations) {
 | 
				
			||||||
		String rootPath = this.endpointPathMapper.getRootPath(id);
 | 
							String rootPath = this.endpointPathMapper.getRootPath(id);
 | 
				
			||||||
		return new DiscoveredControllerEndpoint(this, endpointBean, id, rootPath,
 | 
							return new DiscoveredControllerEndpoint(this, endpointBean, id, rootPath,
 | 
				
			||||||
				enabledByDefault);
 | 
									enabledByDefault);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
 | 
						@Deprecated
 | 
				
			||||||
	protected Operation createOperation(String endpointId,
 | 
						protected Operation createOperation(String endpointId,
 | 
				
			||||||
			DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
 | 
								DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
 | 
				
			||||||
 | 
							return createOperation(EndpointId.of(endpointId), operationMethod, invoker);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						protected Operation createOperation(EndpointId endpointId,
 | 
				
			||||||
 | 
								DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
 | 
				
			||||||
		throw new IllegalStateException(
 | 
							throw new IllegalStateException(
 | 
				
			||||||
				"ControllerEndpoints must not declare operations");
 | 
									"ControllerEndpoints must not declare operations");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,7 @@ package org.springframework.boot.actuate.endpoint.web.annotation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.Collections;
 | 
					import java.util.Collections;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.Operation;
 | 
					import org.springframework.boot.actuate.endpoint.Operation;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredEndpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer;
 | 
				
			||||||
| 
						 | 
					@ -33,7 +34,7 @@ class DiscoveredControllerEndpoint extends AbstractDiscoveredEndpoint<Operation>
 | 
				
			||||||
	private final String rootPath;
 | 
						private final String rootPath;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DiscoveredControllerEndpoint(EndpointDiscoverer<?, ?> discoverer, Object endpointBean,
 | 
						DiscoveredControllerEndpoint(EndpointDiscoverer<?, ?> discoverer, Object endpointBean,
 | 
				
			||||||
			String id, String rootPath, boolean enabledByDefault) {
 | 
								EndpointId id, String rootPath, boolean enabledByDefault) {
 | 
				
			||||||
		super(discoverer, endpointBean, id, enabledByDefault, Collections.emptyList());
 | 
							super(discoverer, endpointBean, id, enabledByDefault, Collections.emptyList());
 | 
				
			||||||
		this.rootPath = rootPath;
 | 
							this.rootPath = rootPath;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,7 @@ package org.springframework.boot.actuate.endpoint.web.annotation;
 | 
				
			||||||
import java.util.Collections;
 | 
					import java.util.Collections;
 | 
				
			||||||
import java.util.function.Supplier;
 | 
					import java.util.function.Supplier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.Operation;
 | 
					import org.springframework.boot.actuate.endpoint.Operation;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredEndpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer;
 | 
				
			||||||
| 
						 | 
					@ -39,7 +40,7 @@ class DiscoveredServletEndpoint extends AbstractDiscoveredEndpoint<Operation>
 | 
				
			||||||
	private final EndpointServlet endpointServlet;
 | 
						private final EndpointServlet endpointServlet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DiscoveredServletEndpoint(EndpointDiscoverer<?, ?> discoverer, Object endpointBean,
 | 
						DiscoveredServletEndpoint(EndpointDiscoverer<?, ?> discoverer, Object endpointBean,
 | 
				
			||||||
			String id, String rootPath, boolean enabledByDefault) {
 | 
								EndpointId id, String rootPath, boolean enabledByDefault) {
 | 
				
			||||||
		super(discoverer, endpointBean, id, enabledByDefault, Collections.emptyList());
 | 
							super(discoverer, endpointBean, id, enabledByDefault, Collections.emptyList());
 | 
				
			||||||
		String beanType = endpointBean.getClass().getName();
 | 
							String beanType = endpointBean.getClass().getName();
 | 
				
			||||||
		Assert.state(endpointBean instanceof Supplier,
 | 
							Assert.state(endpointBean instanceof Supplier,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,7 @@ package org.springframework.boot.actuate.endpoint.web.annotation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.Collection;
 | 
					import java.util.Collection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredEndpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
 | 
				
			||||||
| 
						 | 
					@ -34,7 +35,7 @@ class DiscoveredWebEndpoint extends AbstractDiscoveredEndpoint<WebOperation>
 | 
				
			||||||
	private final String rootPath;
 | 
						private final String rootPath;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DiscoveredWebEndpoint(EndpointDiscoverer<?, ?> discoverer, Object endpointBean,
 | 
						DiscoveredWebEndpoint(EndpointDiscoverer<?, ?> discoverer, Object endpointBean,
 | 
				
			||||||
			String id, String rootPath, boolean enabledByDefault,
 | 
								EndpointId id, String rootPath, boolean enabledByDefault,
 | 
				
			||||||
			Collection<WebOperation> operations) {
 | 
								Collection<WebOperation> operations) {
 | 
				
			||||||
		super(discoverer, endpointBean, id, enabledByDefault, operations);
 | 
							super(discoverer, endpointBean, id, enabledByDefault, operations);
 | 
				
			||||||
		this.rootPath = rootPath;
 | 
							this.rootPath = rootPath;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,7 @@ import java.util.stream.Stream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.reactivestreams.Publisher;
 | 
					import org.reactivestreams.Publisher;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredOperation;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredOperation;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.DiscoveredOperationMethod;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.DiscoveredOperationMethod;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.Selector;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.Selector;
 | 
				
			||||||
| 
						 | 
					@ -51,8 +52,9 @@ class DiscoveredWebOperation extends AbstractDiscoveredOperation implements WebO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final WebOperationRequestPredicate requestPredicate;
 | 
						private final WebOperationRequestPredicate requestPredicate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DiscoveredWebOperation(String endpointId, DiscoveredOperationMethod operationMethod,
 | 
						DiscoveredWebOperation(EndpointId endpointId,
 | 
				
			||||||
			OperationInvoker invoker, WebOperationRequestPredicate requestPredicate) {
 | 
								DiscoveredOperationMethod operationMethod, OperationInvoker invoker,
 | 
				
			||||||
 | 
								WebOperationRequestPredicate requestPredicate) {
 | 
				
			||||||
		super(operationMethod, invoker);
 | 
							super(operationMethod, invoker);
 | 
				
			||||||
		Method method = operationMethod.getMethod();
 | 
							Method method = operationMethod.getMethod();
 | 
				
			||||||
		this.id = getId(endpointId, method);
 | 
							this.id = getId(endpointId, method);
 | 
				
			||||||
| 
						 | 
					@ -60,7 +62,7 @@ class DiscoveredWebOperation extends AbstractDiscoveredOperation implements WebO
 | 
				
			||||||
		this.requestPredicate = requestPredicate;
 | 
							this.requestPredicate = requestPredicate;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private String getId(String endpointId, Method method) {
 | 
						private String getId(EndpointId endpointId, Method method) {
 | 
				
			||||||
		return endpointId + Stream.of(method.getParameters()).filter(this::hasSelector)
 | 
							return endpointId + Stream.of(method.getParameters()).filter(this::hasSelector)
 | 
				
			||||||
				.map(this::dashName).collect(Collectors.joining());
 | 
									.map(this::dashName).collect(Collectors.joining());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,7 @@ import java.util.Collections;
 | 
				
			||||||
import java.util.stream.Collectors;
 | 
					import java.util.stream.Collectors;
 | 
				
			||||||
import java.util.stream.Stream;
 | 
					import java.util.stream.Stream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.OperationType;
 | 
					import org.springframework.boot.actuate.endpoint.OperationType;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.DiscoveredOperationMethod;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.DiscoveredOperationMethod;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.Selector;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.Selector;
 | 
				
			||||||
| 
						 | 
					@ -50,7 +51,7 @@ class RequestPredicateFactory {
 | 
				
			||||||
		this.endpointMediaTypes = endpointMediaTypes;
 | 
							this.endpointMediaTypes = endpointMediaTypes;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public WebOperationRequestPredicate getRequestPredicate(String endpointId,
 | 
						public WebOperationRequestPredicate getRequestPredicate(EndpointId endpointId,
 | 
				
			||||||
			String rootPath, DiscoveredOperationMethod operationMethod) {
 | 
								String rootPath, DiscoveredOperationMethod operationMethod) {
 | 
				
			||||||
		Method method = operationMethod.getMethod();
 | 
							Method method = operationMethod.getMethod();
 | 
				
			||||||
		String path = getPath(rootPath, method);
 | 
							String path = getPath(rootPath, method);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,7 @@ import java.util.Collection;
 | 
				
			||||||
import java.util.Collections;
 | 
					import java.util.Collections;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.EndpointFilter;
 | 
					import org.springframework.boot.actuate.endpoint.EndpointFilter;
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.Operation;
 | 
					import org.springframework.boot.actuate.endpoint.Operation;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.DiscoveredOperationMethod;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.DiscoveredOperationMethod;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer;
 | 
				
			||||||
| 
						 | 
					@ -66,16 +67,31 @@ public class ServletEndpointDiscoverer
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
 | 
						@Deprecated
 | 
				
			||||||
	protected ExposableServletEndpoint createEndpoint(Object endpointBean, String id,
 | 
						protected ExposableServletEndpoint createEndpoint(Object endpointBean, String id,
 | 
				
			||||||
			boolean enabledByDefault, Collection<Operation> operations) {
 | 
								boolean enabledByDefault, Collection<Operation> operations) {
 | 
				
			||||||
 | 
							return createEndpoint(endpointBean, EndpointId.of(id), enabledByDefault,
 | 
				
			||||||
 | 
									operations);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						protected ExposableServletEndpoint createEndpoint(Object endpointBean, EndpointId id,
 | 
				
			||||||
 | 
								boolean enabledByDefault, Collection<Operation> operations) {
 | 
				
			||||||
		String rootPath = this.endpointPathMapper.getRootPath(id);
 | 
							String rootPath = this.endpointPathMapper.getRootPath(id);
 | 
				
			||||||
		return new DiscoveredServletEndpoint(this, endpointBean, id, rootPath,
 | 
							return new DiscoveredServletEndpoint(this, endpointBean, id, rootPath,
 | 
				
			||||||
				enabledByDefault);
 | 
									enabledByDefault);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
 | 
						@Deprecated
 | 
				
			||||||
	protected Operation createOperation(String endpointId,
 | 
						protected Operation createOperation(String endpointId,
 | 
				
			||||||
			DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
 | 
								DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
 | 
				
			||||||
 | 
							return createOperation(EndpointId.of(endpointId), operationMethod, invoker);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						protected Operation createOperation(EndpointId endpointId,
 | 
				
			||||||
 | 
								DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
 | 
				
			||||||
		throw new IllegalStateException("ServletEndpoints must not declare operations");
 | 
							throw new IllegalStateException("ServletEndpoints must not declare operations");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,7 @@ package org.springframework.boot.actuate.endpoint.web.annotation;
 | 
				
			||||||
import java.util.Collection;
 | 
					import java.util.Collection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.EndpointFilter;
 | 
					import org.springframework.boot.actuate.endpoint.EndpointFilter;
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.DiscoveredOperationMethod;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.DiscoveredOperationMethod;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.invoke.OperationInvoker;
 | 
					import org.springframework.boot.actuate.endpoint.invoke.OperationInvoker;
 | 
				
			||||||
| 
						 | 
					@ -68,16 +69,31 @@ public class WebEndpointDiscoverer
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
 | 
						@Deprecated
 | 
				
			||||||
	protected ExposableWebEndpoint createEndpoint(Object endpointBean, String id,
 | 
						protected ExposableWebEndpoint createEndpoint(Object endpointBean, String id,
 | 
				
			||||||
			boolean enabledByDefault, Collection<WebOperation> operations) {
 | 
								boolean enabledByDefault, Collection<WebOperation> operations) {
 | 
				
			||||||
 | 
							return createEndpoint(endpointBean, EndpointId.of(id), enabledByDefault,
 | 
				
			||||||
 | 
									operations);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						protected ExposableWebEndpoint createEndpoint(Object endpointBean, EndpointId id,
 | 
				
			||||||
 | 
								boolean enabledByDefault, Collection<WebOperation> operations) {
 | 
				
			||||||
		String rootPath = this.endpointPathMapper.getRootPath(id);
 | 
							String rootPath = this.endpointPathMapper.getRootPath(id);
 | 
				
			||||||
		return new DiscoveredWebEndpoint(this, endpointBean, id, rootPath,
 | 
							return new DiscoveredWebEndpoint(this, endpointBean, id, rootPath,
 | 
				
			||||||
				enabledByDefault, operations);
 | 
									enabledByDefault, operations);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
 | 
						@Deprecated
 | 
				
			||||||
	protected WebOperation createOperation(String endpointId,
 | 
						protected WebOperation createOperation(String endpointId,
 | 
				
			||||||
			DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
 | 
								DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
 | 
				
			||||||
 | 
							return createOperation(EndpointId.of(endpointId), operationMethod, invoker);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						protected WebOperation createOperation(EndpointId endpointId,
 | 
				
			||||||
 | 
								DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
 | 
				
			||||||
		String rootPath = this.endpointPathMapper.getRootPath(endpointId);
 | 
							String rootPath = this.endpointPathMapper.getRootPath(endpointId);
 | 
				
			||||||
		WebOperationRequestPredicate requestPredicate = this.requestPredicateFactory
 | 
							WebOperationRequestPredicate requestPredicate = this.requestPredicateFactory
 | 
				
			||||||
				.getRequestPredicate(endpointId, rootPath, operationMethod);
 | 
									.getRequestPredicate(endpointId, rootPath, operationMethod);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,102 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright 2012-2018 the original author or authors.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package org.springframework.boot.actuate.endpoint;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.junit.Rule;
 | 
				
			||||||
 | 
					import org.junit.Test;
 | 
				
			||||||
 | 
					import org.junit.rules.ExpectedException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import static org.assertj.core.api.Assertions.assertThat;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Tests for {@link EndpointId}.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @author Phillip Webb
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public class EndpointIdTests {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Rule
 | 
				
			||||||
 | 
						public ExpectedException thrown = ExpectedException.none();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						public void ofWhenNullThorowsException() {
 | 
				
			||||||
 | 
							this.thrown.expect(IllegalArgumentException.class);
 | 
				
			||||||
 | 
							this.thrown.expectMessage("Value must not be empty");
 | 
				
			||||||
 | 
							EndpointId.of(null);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						public void ofWhenEmptyThrowsException() {
 | 
				
			||||||
 | 
							this.thrown.expect(IllegalArgumentException.class);
 | 
				
			||||||
 | 
							this.thrown.expectMessage("Value must not be empty");
 | 
				
			||||||
 | 
							EndpointId.of("");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						public void ofWhenContainsDashThrowsException() {
 | 
				
			||||||
 | 
							this.thrown.expect(IllegalArgumentException.class);
 | 
				
			||||||
 | 
							this.thrown.expectMessage("Value must be alpha-numeric");
 | 
				
			||||||
 | 
							EndpointId.of("foo-bar");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						public void ofWhenHasBadCharThrowsException() {
 | 
				
			||||||
 | 
							this.thrown.expect(IllegalArgumentException.class);
 | 
				
			||||||
 | 
							this.thrown.expectMessage("Value must be alpha-numeric");
 | 
				
			||||||
 | 
							EndpointId.of("foo!bar");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						public void ofWhenStartsWithNumberThrowsException() {
 | 
				
			||||||
 | 
							this.thrown.expect(IllegalArgumentException.class);
 | 
				
			||||||
 | 
							this.thrown.expectMessage("Value must not start with a number");
 | 
				
			||||||
 | 
							EndpointId.of("1foo");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						public void ofWhenStartsWithUppercaseLetterThrowsException() {
 | 
				
			||||||
 | 
							this.thrown.expect(IllegalArgumentException.class);
 | 
				
			||||||
 | 
							this.thrown.expectMessage("Value must not start with an uppercase letter");
 | 
				
			||||||
 | 
							EndpointId.of("Foo");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						public void equalsAndHashCode() {
 | 
				
			||||||
 | 
							EndpointId one = EndpointId.of("foobar");
 | 
				
			||||||
 | 
							EndpointId two = EndpointId.of("fooBar");
 | 
				
			||||||
 | 
							EndpointId three = EndpointId.of("barfoo");
 | 
				
			||||||
 | 
							assertThat(one.hashCode()).isEqualTo(two.hashCode());
 | 
				
			||||||
 | 
							assertThat(one).isEqualTo(one).isEqualTo(two).isNotEqualTo(three);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						public void toLowerCaseStringReturnsLowercase() {
 | 
				
			||||||
 | 
							assertThat(EndpointId.of("fooBar").toLowerCaseString()).isEqualTo("foobar");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						public void toStringReturnsString() {
 | 
				
			||||||
 | 
							assertThat(EndpointId.of("fooBar").toString()).isEqualTo("fooBar");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						public void fromPropertyValueStripsDashes() {
 | 
				
			||||||
 | 
							EndpointId fromPropertyValue = EndpointId.fromPropertyValue("foo-bar");
 | 
				
			||||||
 | 
							assertThat(fromPropertyValue).isEqualTo(EndpointId.of("fooBar"));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -25,6 +25,7 @@ import java.util.Map;
 | 
				
			||||||
import org.junit.Before;
 | 
					import org.junit.Before;
 | 
				
			||||||
import org.junit.Test;
 | 
					import org.junit.Test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.InvocationContext;
 | 
					import org.springframework.boot.actuate.endpoint.InvocationContext;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.OperationType;
 | 
					import org.springframework.boot.actuate.endpoint.OperationType;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.SecurityContext;
 | 
					import org.springframework.boot.actuate.endpoint.SecurityContext;
 | 
				
			||||||
| 
						 | 
					@ -60,8 +61,8 @@ public class DiscoveredOperationsFactoryTests {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void createOperationsWhenHasReadMethodShouldCreateOperation() {
 | 
						public void createOperationsWhenHasReadMethodShouldCreateOperation() {
 | 
				
			||||||
		Collection<TestOperation> operations = this.factory.createOperations("test",
 | 
							Collection<TestOperation> operations = this.factory
 | 
				
			||||||
				new ExampleRead());
 | 
									.createOperations(EndpointId.of("test"), new ExampleRead());
 | 
				
			||||||
		assertThat(operations).hasSize(1);
 | 
							assertThat(operations).hasSize(1);
 | 
				
			||||||
		TestOperation operation = getFirst(operations);
 | 
							TestOperation operation = getFirst(operations);
 | 
				
			||||||
		assertThat(operation.getType()).isEqualTo(OperationType.READ);
 | 
							assertThat(operation.getType()).isEqualTo(OperationType.READ);
 | 
				
			||||||
| 
						 | 
					@ -69,8 +70,8 @@ public class DiscoveredOperationsFactoryTests {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void createOperationsWhenHasWriteMethodShouldCreateOperation() {
 | 
						public void createOperationsWhenHasWriteMethodShouldCreateOperation() {
 | 
				
			||||||
		Collection<TestOperation> operations = this.factory.createOperations("test",
 | 
							Collection<TestOperation> operations = this.factory
 | 
				
			||||||
				new ExampleWrite());
 | 
									.createOperations(EndpointId.of("test"), new ExampleWrite());
 | 
				
			||||||
		assertThat(operations).hasSize(1);
 | 
							assertThat(operations).hasSize(1);
 | 
				
			||||||
		TestOperation operation = getFirst(operations);
 | 
							TestOperation operation = getFirst(operations);
 | 
				
			||||||
		assertThat(operation.getType()).isEqualTo(OperationType.WRITE);
 | 
							assertThat(operation.getType()).isEqualTo(OperationType.WRITE);
 | 
				
			||||||
| 
						 | 
					@ -78,8 +79,8 @@ public class DiscoveredOperationsFactoryTests {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void createOperationsWhenHasDeleteMethodShouldCreateOperation() {
 | 
						public void createOperationsWhenHasDeleteMethodShouldCreateOperation() {
 | 
				
			||||||
		Collection<TestOperation> operations = this.factory.createOperations("test",
 | 
							Collection<TestOperation> operations = this.factory
 | 
				
			||||||
				new ExampleDelete());
 | 
									.createOperations(EndpointId.of("test"), new ExampleDelete());
 | 
				
			||||||
		assertThat(operations).hasSize(1);
 | 
							assertThat(operations).hasSize(1);
 | 
				
			||||||
		TestOperation operation = getFirst(operations);
 | 
							TestOperation operation = getFirst(operations);
 | 
				
			||||||
		assertThat(operation.getType()).isEqualTo(OperationType.DELETE);
 | 
							assertThat(operation.getType()).isEqualTo(OperationType.DELETE);
 | 
				
			||||||
| 
						 | 
					@ -87,8 +88,8 @@ public class DiscoveredOperationsFactoryTests {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void createOperationsWhenMultipleShouldReturnMultiple() {
 | 
						public void createOperationsWhenMultipleShouldReturnMultiple() {
 | 
				
			||||||
		Collection<TestOperation> operations = this.factory.createOperations("test",
 | 
							Collection<TestOperation> operations = this.factory
 | 
				
			||||||
				new ExampleMultiple());
 | 
									.createOperations(EndpointId.of("test"), new ExampleMultiple());
 | 
				
			||||||
		assertThat(operations).hasSize(2);
 | 
							assertThat(operations).hasSize(2);
 | 
				
			||||||
		assertThat(operations.stream().map(TestOperation::getType))
 | 
							assertThat(operations.stream().map(TestOperation::getType))
 | 
				
			||||||
				.containsOnly(OperationType.READ, OperationType.WRITE);
 | 
									.containsOnly(OperationType.READ, OperationType.WRITE);
 | 
				
			||||||
| 
						 | 
					@ -96,8 +97,8 @@ public class DiscoveredOperationsFactoryTests {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void createOperationsShouldProvideOperationMethod() {
 | 
						public void createOperationsShouldProvideOperationMethod() {
 | 
				
			||||||
		TestOperation operation = getFirst(
 | 
							TestOperation operation = getFirst(this.factory
 | 
				
			||||||
				this.factory.createOperations("test", new ExampleWithParams()));
 | 
									.createOperations(EndpointId.of("test"), new ExampleWithParams()));
 | 
				
			||||||
		OperationMethod operationMethod = operation.getOperationMethod();
 | 
							OperationMethod operationMethod = operation.getOperationMethod();
 | 
				
			||||||
		assertThat(operationMethod.getMethod().getName()).isEqualTo("read");
 | 
							assertThat(operationMethod.getMethod().getName()).isEqualTo("read");
 | 
				
			||||||
		assertThat(operationMethod.getParameters().hasParameters()).isTrue();
 | 
							assertThat(operationMethod.getParameters().hasParameters()).isTrue();
 | 
				
			||||||
| 
						 | 
					@ -105,8 +106,8 @@ public class DiscoveredOperationsFactoryTests {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void createOperationsShouldProviderInvoker() {
 | 
						public void createOperationsShouldProviderInvoker() {
 | 
				
			||||||
		TestOperation operation = getFirst(
 | 
							TestOperation operation = getFirst(this.factory
 | 
				
			||||||
				this.factory.createOperations("test", new ExampleWithParams()));
 | 
									.createOperations(EndpointId.of("test"), new ExampleWithParams()));
 | 
				
			||||||
		Map<String, Object> params = Collections.singletonMap("name", 123);
 | 
							Map<String, Object> params = Collections.singletonMap("name", 123);
 | 
				
			||||||
		Object result = operation
 | 
							Object result = operation
 | 
				
			||||||
				.invoke(new InvocationContext(mock(SecurityContext.class), params));
 | 
									.invoke(new InvocationContext(mock(SecurityContext.class), params));
 | 
				
			||||||
| 
						 | 
					@ -118,10 +119,10 @@ public class DiscoveredOperationsFactoryTests {
 | 
				
			||||||
		TestOperationInvokerAdvisor advisor = new TestOperationInvokerAdvisor();
 | 
							TestOperationInvokerAdvisor advisor = new TestOperationInvokerAdvisor();
 | 
				
			||||||
		this.invokerAdvisors.add(advisor);
 | 
							this.invokerAdvisors.add(advisor);
 | 
				
			||||||
		TestOperation operation = getFirst(
 | 
							TestOperation operation = getFirst(
 | 
				
			||||||
				this.factory.createOperations("test", new ExampleRead()));
 | 
									this.factory.createOperations(EndpointId.of("test"), new ExampleRead()));
 | 
				
			||||||
		operation.invoke(new InvocationContext(mock(SecurityContext.class),
 | 
							operation.invoke(new InvocationContext(mock(SecurityContext.class),
 | 
				
			||||||
				Collections.emptyMap()));
 | 
									Collections.emptyMap()));
 | 
				
			||||||
		assertThat(advisor.getEndpointId()).isEqualTo("test");
 | 
							assertThat(advisor.getEndpointId()).isEqualTo(EndpointId.of("test"));
 | 
				
			||||||
		assertThat(advisor.getOperationType()).isEqualTo(OperationType.READ);
 | 
							assertThat(advisor.getOperationType()).isEqualTo(OperationType.READ);
 | 
				
			||||||
		assertThat(advisor.getParameters()).isEmpty();
 | 
							assertThat(advisor.getParameters()).isEmpty();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -189,7 +190,7 @@ public class DiscoveredOperationsFactoryTests {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		@Override
 | 
							@Override
 | 
				
			||||||
		protected TestOperation createOperation(String endpointId,
 | 
							protected TestOperation createOperation(EndpointId endpointId,
 | 
				
			||||||
				DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
 | 
									DiscoveredOperationMethod operationMethod, OperationInvoker invoker) {
 | 
				
			||||||
			return new TestOperation(endpointId, operationMethod, invoker);
 | 
								return new TestOperation(endpointId, operationMethod, invoker);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -198,7 +199,7 @@ public class DiscoveredOperationsFactoryTests {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static class TestOperation extends AbstractDiscoveredOperation {
 | 
						static class TestOperation extends AbstractDiscoveredOperation {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		TestOperation(String endpointId, DiscoveredOperationMethod operationMethod,
 | 
							TestOperation(EndpointId endpointId, DiscoveredOperationMethod operationMethod,
 | 
				
			||||||
				OperationInvoker invoker) {
 | 
									OperationInvoker invoker) {
 | 
				
			||||||
			super(operationMethod, invoker);
 | 
								super(operationMethod, invoker);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -207,14 +208,14 @@ public class DiscoveredOperationsFactoryTests {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static class TestOperationInvokerAdvisor implements OperationInvokerAdvisor {
 | 
						static class TestOperationInvokerAdvisor implements OperationInvokerAdvisor {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private String endpointId;
 | 
							private EndpointId endpointId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private OperationType operationType;
 | 
							private OperationType operationType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private OperationParameters parameters;
 | 
							private OperationParameters parameters;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		@Override
 | 
							@Override
 | 
				
			||||||
		public OperationInvoker apply(String endpointId, OperationType operationType,
 | 
							public OperationInvoker apply(EndpointId endpointId, OperationType operationType,
 | 
				
			||||||
				OperationParameters parameters, OperationInvoker invoker) {
 | 
									OperationParameters parameters, OperationInvoker invoker) {
 | 
				
			||||||
			this.endpointId = endpointId;
 | 
								this.endpointId = endpointId;
 | 
				
			||||||
			this.operationType = operationType;
 | 
								this.operationType = operationType;
 | 
				
			||||||
| 
						 | 
					@ -222,7 +223,14 @@ public class DiscoveredOperationsFactoryTests {
 | 
				
			||||||
			return invoker;
 | 
								return invoker;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public String getEndpointId() {
 | 
							@Override
 | 
				
			||||||
 | 
							@Deprecated
 | 
				
			||||||
 | 
							public OperationInvoker apply(String endpointId, OperationType operationType,
 | 
				
			||||||
 | 
									OperationParameters parameters, OperationInvoker invoker) {
 | 
				
			||||||
 | 
								throw new IllegalStateException();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public EndpointId getEndpointId() {
 | 
				
			||||||
			return this.endpointId;
 | 
								return this.endpointId;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,6 +37,7 @@ import org.junit.Test;
 | 
				
			||||||
import org.junit.rules.ExpectedException;
 | 
					import org.junit.rules.ExpectedException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.EndpointFilter;
 | 
					import org.springframework.boot.actuate.endpoint.EndpointFilter;
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.Operation;
 | 
					import org.springframework.boot.actuate.endpoint.Operation;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.invoke.OperationInvoker;
 | 
					import org.springframework.boot.actuate.endpoint.invoke.OperationInvoker;
 | 
				
			||||||
| 
						 | 
					@ -125,10 +126,11 @@ public class EndpointDiscovererTests {
 | 
				
			||||||
	public void getEndpointsWhenHasSubclassedEndpointShouldReturnEndpoint() {
 | 
						public void getEndpointsWhenHasSubclassedEndpointShouldReturnEndpoint() {
 | 
				
			||||||
		load(TestEndpointSubclassConfiguration.class, (context) -> {
 | 
							load(TestEndpointSubclassConfiguration.class, (context) -> {
 | 
				
			||||||
			TestEndpointDiscoverer discoverer = new TestEndpointDiscoverer(context);
 | 
								TestEndpointDiscoverer discoverer = new TestEndpointDiscoverer(context);
 | 
				
			||||||
			Map<String, TestExposableEndpoint> endpoints = mapEndpoints(
 | 
								Map<EndpointId, TestExposableEndpoint> endpoints = mapEndpoints(
 | 
				
			||||||
					discoverer.getEndpoints());
 | 
										discoverer.getEndpoints());
 | 
				
			||||||
			assertThat(endpoints).containsOnlyKeys("test");
 | 
								assertThat(endpoints).containsOnlyKeys(EndpointId.of("test"));
 | 
				
			||||||
			Map<Method, TestOperation> operations = mapOperations(endpoints.get("test"));
 | 
								Map<Method, TestOperation> operations = mapOperations(
 | 
				
			||||||
 | 
										endpoints.get(EndpointId.of("test")));
 | 
				
			||||||
			assertThat(operations).hasSize(5);
 | 
								assertThat(operations).hasSize(5);
 | 
				
			||||||
			assertThat(operations).containsKeys(testEndpointMethods());
 | 
								assertThat(operations).containsKeys(testEndpointMethods());
 | 
				
			||||||
			assertThat(operations).containsKeys(ReflectionUtils.findMethod(
 | 
								assertThat(operations).containsKeys(ReflectionUtils.findMethod(
 | 
				
			||||||
| 
						 | 
					@ -151,10 +153,11 @@ public class EndpointDiscovererTests {
 | 
				
			||||||
		load(TestEndpointConfiguration.class, (context) -> {
 | 
							load(TestEndpointConfiguration.class, (context) -> {
 | 
				
			||||||
			TestEndpointDiscoverer discoverer = new TestEndpointDiscoverer(context,
 | 
								TestEndpointDiscoverer discoverer = new TestEndpointDiscoverer(context,
 | 
				
			||||||
					(endpointId) -> 0L);
 | 
										(endpointId) -> 0L);
 | 
				
			||||||
			Map<String, TestExposableEndpoint> endpoints = mapEndpoints(
 | 
								Map<EndpointId, TestExposableEndpoint> endpoints = mapEndpoints(
 | 
				
			||||||
					discoverer.getEndpoints());
 | 
										discoverer.getEndpoints());
 | 
				
			||||||
			assertThat(endpoints).containsOnlyKeys("test");
 | 
								assertThat(endpoints).containsOnlyKeys(EndpointId.of("test"));
 | 
				
			||||||
			Map<Method, TestOperation> operations = mapOperations(endpoints.get("test"));
 | 
								Map<Method, TestOperation> operations = mapOperations(
 | 
				
			||||||
 | 
										endpoints.get(EndpointId.of("test")));
 | 
				
			||||||
			operations.values().forEach((operation) -> assertThat(operation.getInvoker())
 | 
								operations.values().forEach((operation) -> assertThat(operation.getInvoker())
 | 
				
			||||||
					.isNotInstanceOf(CachingOperationInvoker.class));
 | 
										.isNotInstanceOf(CachingOperationInvoker.class));
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
| 
						 | 
					@ -165,10 +168,11 @@ public class EndpointDiscovererTests {
 | 
				
			||||||
		load(TestEndpointConfiguration.class, (context) -> {
 | 
							load(TestEndpointConfiguration.class, (context) -> {
 | 
				
			||||||
			TestEndpointDiscoverer discoverer = new TestEndpointDiscoverer(context,
 | 
								TestEndpointDiscoverer discoverer = new TestEndpointDiscoverer(context,
 | 
				
			||||||
					(endpointId) -> (endpointId.equals("foo") ? 500L : 0L));
 | 
										(endpointId) -> (endpointId.equals("foo") ? 500L : 0L));
 | 
				
			||||||
			Map<String, TestExposableEndpoint> endpoints = mapEndpoints(
 | 
								Map<EndpointId, TestExposableEndpoint> endpoints = mapEndpoints(
 | 
				
			||||||
					discoverer.getEndpoints());
 | 
										discoverer.getEndpoints());
 | 
				
			||||||
			assertThat(endpoints).containsOnlyKeys("test");
 | 
								assertThat(endpoints).containsOnlyKeys(EndpointId.of("test"));
 | 
				
			||||||
			Map<Method, TestOperation> operations = mapOperations(endpoints.get("test"));
 | 
								Map<Method, TestOperation> operations = mapOperations(
 | 
				
			||||||
 | 
										endpoints.get(EndpointId.of("test")));
 | 
				
			||||||
			operations.values().forEach((operation) -> assertThat(operation.getInvoker())
 | 
								operations.values().forEach((operation) -> assertThat(operation.getInvoker())
 | 
				
			||||||
					.isNotInstanceOf(CachingOperationInvoker.class));
 | 
										.isNotInstanceOf(CachingOperationInvoker.class));
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
| 
						 | 
					@ -178,11 +182,13 @@ public class EndpointDiscovererTests {
 | 
				
			||||||
	public void getEndpointsWhenTtlSetByIdAndIdMatchesShouldCacheInvokeCalls() {
 | 
						public void getEndpointsWhenTtlSetByIdAndIdMatchesShouldCacheInvokeCalls() {
 | 
				
			||||||
		load(TestEndpointConfiguration.class, (context) -> {
 | 
							load(TestEndpointConfiguration.class, (context) -> {
 | 
				
			||||||
			TestEndpointDiscoverer discoverer = new TestEndpointDiscoverer(context,
 | 
								TestEndpointDiscoverer discoverer = new TestEndpointDiscoverer(context,
 | 
				
			||||||
					(endpointId) -> (endpointId.equals("test") ? 500L : 0L));
 | 
										(endpointId) -> (endpointId.equals(EndpointId.of("test")) ? 500L
 | 
				
			||||||
			Map<String, TestExposableEndpoint> endpoints = mapEndpoints(
 | 
												: 0L));
 | 
				
			||||||
 | 
								Map<EndpointId, TestExposableEndpoint> endpoints = mapEndpoints(
 | 
				
			||||||
					discoverer.getEndpoints());
 | 
										discoverer.getEndpoints());
 | 
				
			||||||
			assertThat(endpoints).containsOnlyKeys("test");
 | 
								assertThat(endpoints).containsOnlyKeys(EndpointId.of("test"));
 | 
				
			||||||
			Map<Method, TestOperation> operations = mapOperations(endpoints.get("test"));
 | 
								Map<Method, TestOperation> operations = mapOperations(
 | 
				
			||||||
 | 
										endpoints.get(EndpointId.of("test")));
 | 
				
			||||||
			TestOperation getAll = operations.get(findTestEndpointMethod("getAll"));
 | 
								TestOperation getAll = operations.get(findTestEndpointMethod("getAll"));
 | 
				
			||||||
			TestOperation getOne = operations
 | 
								TestOperation getOne = operations
 | 
				
			||||||
					.get(findTestEndpointMethod("getOne", String.class));
 | 
										.get(findTestEndpointMethod("getOne", String.class));
 | 
				
			||||||
| 
						 | 
					@ -201,9 +207,9 @@ public class EndpointDiscovererTests {
 | 
				
			||||||
	public void getEndpointsWhenHasSpecializedFiltersInNonSpecializedDiscovererShouldFilterEndpoints() {
 | 
						public void getEndpointsWhenHasSpecializedFiltersInNonSpecializedDiscovererShouldFilterEndpoints() {
 | 
				
			||||||
		load(SpecializedEndpointsConfiguration.class, (context) -> {
 | 
							load(SpecializedEndpointsConfiguration.class, (context) -> {
 | 
				
			||||||
			TestEndpointDiscoverer discoverer = new TestEndpointDiscoverer(context);
 | 
								TestEndpointDiscoverer discoverer = new TestEndpointDiscoverer(context);
 | 
				
			||||||
			Map<String, TestExposableEndpoint> endpoints = mapEndpoints(
 | 
								Map<EndpointId, TestExposableEndpoint> endpoints = mapEndpoints(
 | 
				
			||||||
					discoverer.getEndpoints());
 | 
										discoverer.getEndpoints());
 | 
				
			||||||
			assertThat(endpoints).containsOnlyKeys("test");
 | 
								assertThat(endpoints).containsOnlyKeys(EndpointId.of("test"));
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -212,9 +218,10 @@ public class EndpointDiscovererTests {
 | 
				
			||||||
		load(SpecializedEndpointsConfiguration.class, (context) -> {
 | 
							load(SpecializedEndpointsConfiguration.class, (context) -> {
 | 
				
			||||||
			SpecializedEndpointDiscoverer discoverer = new SpecializedEndpointDiscoverer(
 | 
								SpecializedEndpointDiscoverer discoverer = new SpecializedEndpointDiscoverer(
 | 
				
			||||||
					context);
 | 
										context);
 | 
				
			||||||
			Map<String, SpecializedExposableEndpoint> endpoints = mapEndpoints(
 | 
								Map<EndpointId, SpecializedExposableEndpoint> endpoints = mapEndpoints(
 | 
				
			||||||
					discoverer.getEndpoints());
 | 
										discoverer.getEndpoints());
 | 
				
			||||||
			assertThat(endpoints).containsOnlyKeys("test", "specialized");
 | 
								assertThat(endpoints).containsOnlyKeys(EndpointId.of("test"),
 | 
				
			||||||
 | 
										EndpointId.of("specialized"));
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -223,10 +230,10 @@ public class EndpointDiscovererTests {
 | 
				
			||||||
		load(SpecializedEndpointsConfiguration.class, (context) -> {
 | 
							load(SpecializedEndpointsConfiguration.class, (context) -> {
 | 
				
			||||||
			SpecializedEndpointDiscoverer discoverer = new SpecializedEndpointDiscoverer(
 | 
								SpecializedEndpointDiscoverer discoverer = new SpecializedEndpointDiscoverer(
 | 
				
			||||||
					context);
 | 
										context);
 | 
				
			||||||
			Map<String, SpecializedExposableEndpoint> endpoints = mapEndpoints(
 | 
								Map<EndpointId, SpecializedExposableEndpoint> endpoints = mapEndpoints(
 | 
				
			||||||
					discoverer.getEndpoints());
 | 
										discoverer.getEndpoints());
 | 
				
			||||||
			Map<Method, SpecializedOperation> operations = mapOperations(
 | 
								Map<Method, SpecializedOperation> operations = mapOperations(
 | 
				
			||||||
					endpoints.get("specialized"));
 | 
										endpoints.get(EndpointId.of("specialized")));
 | 
				
			||||||
			assertThat(operations).containsKeys(
 | 
								assertThat(operations).containsKeys(
 | 
				
			||||||
					ReflectionUtils.findMethod(SpecializedExtension.class, "getSpecial"));
 | 
										ReflectionUtils.findMethod(SpecializedExtension.class, "getSpecial"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -238,10 +245,10 @@ public class EndpointDiscovererTests {
 | 
				
			||||||
		load(SubSpecializedEndpointsConfiguration.class, (context) -> {
 | 
							load(SubSpecializedEndpointsConfiguration.class, (context) -> {
 | 
				
			||||||
			SpecializedEndpointDiscoverer discoverer = new SpecializedEndpointDiscoverer(
 | 
								SpecializedEndpointDiscoverer discoverer = new SpecializedEndpointDiscoverer(
 | 
				
			||||||
					context);
 | 
										context);
 | 
				
			||||||
			Map<String, SpecializedExposableEndpoint> endpoints = mapEndpoints(
 | 
								Map<EndpointId, SpecializedExposableEndpoint> endpoints = mapEndpoints(
 | 
				
			||||||
					discoverer.getEndpoints());
 | 
										discoverer.getEndpoints());
 | 
				
			||||||
			Map<Method, SpecializedOperation> operations = mapOperations(
 | 
								Map<Method, SpecializedOperation> operations = mapOperations(
 | 
				
			||||||
					endpoints.get("specialized"));
 | 
										endpoints.get(EndpointId.of("specialized")));
 | 
				
			||||||
			assertThat(operations).containsKeys(
 | 
								assertThat(operations).containsKeys(
 | 
				
			||||||
					ReflectionUtils.findMethod(SpecializedTestEndpoint.class, "getAll"));
 | 
										ReflectionUtils.findMethod(SpecializedTestEndpoint.class, "getAll"));
 | 
				
			||||||
			assertThat(operations).containsKeys(ReflectionUtils.findMethod(
 | 
								assertThat(operations).containsKeys(ReflectionUtils.findMethod(
 | 
				
			||||||
| 
						 | 
					@ -261,18 +268,19 @@ public class EndpointDiscovererTests {
 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
			SpecializedEndpointDiscoverer discoverer = new SpecializedEndpointDiscoverer(
 | 
								SpecializedEndpointDiscoverer discoverer = new SpecializedEndpointDiscoverer(
 | 
				
			||||||
					context, Collections.singleton(filter));
 | 
										context, Collections.singleton(filter));
 | 
				
			||||||
			Map<String, SpecializedExposableEndpoint> endpoints = mapEndpoints(
 | 
								Map<EndpointId, SpecializedExposableEndpoint> endpoints = mapEndpoints(
 | 
				
			||||||
					discoverer.getEndpoints());
 | 
										discoverer.getEndpoints());
 | 
				
			||||||
			assertThat(endpoints).containsOnlyKeys("test");
 | 
								assertThat(endpoints).containsOnlyKeys(EndpointId.of("test"));
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private void hasTestEndpoint(AnnotationConfigApplicationContext context) {
 | 
						private void hasTestEndpoint(AnnotationConfigApplicationContext context) {
 | 
				
			||||||
		TestEndpointDiscoverer discoverer = new TestEndpointDiscoverer(context);
 | 
							TestEndpointDiscoverer discoverer = new TestEndpointDiscoverer(context);
 | 
				
			||||||
		Map<String, TestExposableEndpoint> endpoints = mapEndpoints(
 | 
							Map<EndpointId, TestExposableEndpoint> endpoints = mapEndpoints(
 | 
				
			||||||
				discoverer.getEndpoints());
 | 
									discoverer.getEndpoints());
 | 
				
			||||||
		assertThat(endpoints).containsOnlyKeys("test");
 | 
							assertThat(endpoints).containsOnlyKeys(EndpointId.of("test"));
 | 
				
			||||||
		Map<Method, TestOperation> operations = mapOperations(endpoints.get("test"));
 | 
							Map<Method, TestOperation> operations = mapOperations(
 | 
				
			||||||
 | 
									endpoints.get(EndpointId.of("test")));
 | 
				
			||||||
		assertThat(operations).hasSize(4);
 | 
							assertThat(operations).hasSize(4);
 | 
				
			||||||
		assertThat(operations).containsKeys();
 | 
							assertThat(operations).containsKeys();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -290,14 +298,15 @@ public class EndpointDiscovererTests {
 | 
				
			||||||
		return ReflectionUtils.findMethod(TestEndpoint.class, name, paramTypes);
 | 
							return ReflectionUtils.findMethod(TestEndpoint.class, name, paramTypes);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private <E extends ExposableEndpoint<?>> Map<String, E> mapEndpoints(
 | 
						private <E extends ExposableEndpoint<?>> Map<EndpointId, E> mapEndpoints(
 | 
				
			||||||
			Collection<E> endpoints) {
 | 
								Collection<E> endpoints) {
 | 
				
			||||||
		Map<String, E> byId = new LinkedHashMap<>();
 | 
							Map<EndpointId, E> byId = new LinkedHashMap<>();
 | 
				
			||||||
		endpoints.forEach((endpoint) -> {
 | 
							endpoints.forEach((endpoint) -> {
 | 
				
			||||||
			E existing = byId.put(endpoint.getId(), endpoint);
 | 
								E existing = byId.put(endpoint.getEndpointId(), endpoint);
 | 
				
			||||||
			if (existing != null) {
 | 
								if (existing != null) {
 | 
				
			||||||
				throw new AssertionError(String.format(
 | 
									throw new AssertionError(
 | 
				
			||||||
						"Found endpoints with duplicate id '%s'", endpoint.getId()));
 | 
											String.format("Found endpoints with duplicate id '%s'",
 | 
				
			||||||
 | 
													endpoint.getEndpointId()));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
		return byId;
 | 
							return byId;
 | 
				
			||||||
| 
						 | 
					@ -491,12 +500,12 @@ public class EndpointDiscovererTests {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		TestEndpointDiscoverer(ApplicationContext applicationContext,
 | 
							TestEndpointDiscoverer(ApplicationContext applicationContext,
 | 
				
			||||||
				Function<String, Long> timeToLive) {
 | 
									Function<EndpointId, Long> timeToLive) {
 | 
				
			||||||
			this(applicationContext, timeToLive, Collections.emptyList());
 | 
								this(applicationContext, timeToLive, Collections.emptyList());
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		TestEndpointDiscoverer(ApplicationContext applicationContext,
 | 
							TestEndpointDiscoverer(ApplicationContext applicationContext,
 | 
				
			||||||
				Function<String, Long> timeToLive,
 | 
									Function<EndpointId, Long> timeToLive,
 | 
				
			||||||
				Collection<EndpointFilter<TestExposableEndpoint>> filters) {
 | 
									Collection<EndpointFilter<TestExposableEndpoint>> filters) {
 | 
				
			||||||
			this(applicationContext, new ConversionServiceParameterValueMapper(),
 | 
								this(applicationContext, new ConversionServiceParameterValueMapper(),
 | 
				
			||||||
					Collections.singleton(new CachingOperationInvokerAdvisor(timeToLive)),
 | 
										Collections.singleton(new CachingOperationInvokerAdvisor(timeToLive)),
 | 
				
			||||||
| 
						 | 
					@ -513,6 +522,12 @@ public class EndpointDiscovererTests {
 | 
				
			||||||
		@Override
 | 
							@Override
 | 
				
			||||||
		protected TestExposableEndpoint createEndpoint(Object endpointBean, String id,
 | 
							protected TestExposableEndpoint createEndpoint(Object endpointBean, String id,
 | 
				
			||||||
				boolean enabledByDefault, Collection<TestOperation> operations) {
 | 
									boolean enabledByDefault, Collection<TestOperation> operations) {
 | 
				
			||||||
 | 
								throw new IllegalStateException();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							@Override
 | 
				
			||||||
 | 
							protected TestExposableEndpoint createEndpoint(Object endpointBean, EndpointId id,
 | 
				
			||||||
 | 
									boolean enabledByDefault, Collection<TestOperation> operations) {
 | 
				
			||||||
			return new TestExposableEndpoint(this, endpointBean, id, enabledByDefault,
 | 
								return new TestExposableEndpoint(this, endpointBean, id, enabledByDefault,
 | 
				
			||||||
					operations);
 | 
										operations);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -548,6 +563,13 @@ public class EndpointDiscovererTests {
 | 
				
			||||||
		protected SpecializedExposableEndpoint createEndpoint(Object endpointBean,
 | 
							protected SpecializedExposableEndpoint createEndpoint(Object endpointBean,
 | 
				
			||||||
				String id, boolean enabledByDefault,
 | 
									String id, boolean enabledByDefault,
 | 
				
			||||||
				Collection<SpecializedOperation> operations) {
 | 
									Collection<SpecializedOperation> operations) {
 | 
				
			||||||
 | 
								throw new IllegalStateException();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							@Override
 | 
				
			||||||
 | 
							protected SpecializedExposableEndpoint createEndpoint(Object endpointBean,
 | 
				
			||||||
 | 
									EndpointId id, boolean enabledByDefault,
 | 
				
			||||||
 | 
									Collection<SpecializedOperation> operations) {
 | 
				
			||||||
			return new SpecializedExposableEndpoint(this, endpointBean, id,
 | 
								return new SpecializedExposableEndpoint(this, endpointBean, id,
 | 
				
			||||||
					enabledByDefault, operations);
 | 
										enabledByDefault, operations);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -569,7 +591,7 @@ public class EndpointDiscovererTests {
 | 
				
			||||||
	static class TestExposableEndpoint extends AbstractDiscoveredEndpoint<TestOperation> {
 | 
						static class TestExposableEndpoint extends AbstractDiscoveredEndpoint<TestOperation> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		TestExposableEndpoint(EndpointDiscoverer<?, ?> discoverer, Object endpointBean,
 | 
							TestExposableEndpoint(EndpointDiscoverer<?, ?> discoverer, Object endpointBean,
 | 
				
			||||||
				String id, boolean enabledByDefault,
 | 
									EndpointId id, boolean enabledByDefault,
 | 
				
			||||||
				Collection<? extends TestOperation> operations) {
 | 
									Collection<? extends TestOperation> operations) {
 | 
				
			||||||
			super(discoverer, endpointBean, id, enabledByDefault, operations);
 | 
								super(discoverer, endpointBean, id, enabledByDefault, operations);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -580,7 +602,7 @@ public class EndpointDiscovererTests {
 | 
				
			||||||
			extends AbstractDiscoveredEndpoint<SpecializedOperation> {
 | 
								extends AbstractDiscoveredEndpoint<SpecializedOperation> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		SpecializedExposableEndpoint(EndpointDiscoverer<?, ?> discoverer,
 | 
							SpecializedExposableEndpoint(EndpointDiscoverer<?, ?> discoverer,
 | 
				
			||||||
				Object endpointBean, String id, boolean enabledByDefault,
 | 
									Object endpointBean, EndpointId id, boolean enabledByDefault,
 | 
				
			||||||
				Collection<? extends SpecializedOperation> operations) {
 | 
									Collection<? extends SpecializedOperation> operations) {
 | 
				
			||||||
			super(discoverer, endpointBean, id, enabledByDefault, operations);
 | 
								super(discoverer, endpointBean, id, enabledByDefault, operations);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,7 @@ import org.junit.Test;
 | 
				
			||||||
import org.mockito.Mock;
 | 
					import org.mockito.Mock;
 | 
				
			||||||
import org.mockito.MockitoAnnotations;
 | 
					import org.mockito.MockitoAnnotations;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.OperationType;
 | 
					import org.springframework.boot.actuate.endpoint.OperationType;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.SecurityContext;
 | 
					import org.springframework.boot.actuate.endpoint.SecurityContext;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.invoke.OperationInvoker;
 | 
					import org.springframework.boot.actuate.endpoint.invoke.OperationInvoker;
 | 
				
			||||||
| 
						 | 
					@ -50,7 +51,7 @@ public class CachingOperationInvokerAdvisorTests {
 | 
				
			||||||
	private OperationInvoker invoker;
 | 
						private OperationInvoker invoker;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Mock
 | 
						@Mock
 | 
				
			||||||
	private Function<String, Long> timeToLive;
 | 
						private Function<EndpointId, Long> timeToLive;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private CachingOperationInvokerAdvisor advisor;
 | 
						private CachingOperationInvokerAdvisor advisor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,8 +64,8 @@ public class CachingOperationInvokerAdvisorTests {
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void applyWhenOperationIsNotReadShouldNotAddAdvise() {
 | 
						public void applyWhenOperationIsNotReadShouldNotAddAdvise() {
 | 
				
			||||||
		OperationParameters parameters = getParameters("get");
 | 
							OperationParameters parameters = getParameters("get");
 | 
				
			||||||
		OperationInvoker advised = this.advisor.apply("foo", OperationType.WRITE,
 | 
							OperationInvoker advised = this.advisor.apply(EndpointId.of("foo"),
 | 
				
			||||||
				parameters, this.invoker);
 | 
									OperationType.WRITE, parameters, this.invoker);
 | 
				
			||||||
		assertThat(advised).isSameAs(this.invoker);
 | 
							assertThat(advised).isSameAs(this.invoker);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -72,8 +73,8 @@ public class CachingOperationInvokerAdvisorTests {
 | 
				
			||||||
	public void applyWhenHasAtLeaseOneMandatoryParameterShouldNotAddAdvise() {
 | 
						public void applyWhenHasAtLeaseOneMandatoryParameterShouldNotAddAdvise() {
 | 
				
			||||||
		OperationParameters parameters = getParameters("getWithParameters", String.class,
 | 
							OperationParameters parameters = getParameters("getWithParameters", String.class,
 | 
				
			||||||
				String.class);
 | 
									String.class);
 | 
				
			||||||
		OperationInvoker advised = this.advisor.apply("foo", OperationType.READ,
 | 
							OperationInvoker advised = this.advisor.apply(EndpointId.of("foo"),
 | 
				
			||||||
				parameters, this.invoker);
 | 
									OperationType.READ, parameters, this.invoker);
 | 
				
			||||||
		assertThat(advised).isSameAs(this.invoker);
 | 
							assertThat(advised).isSameAs(this.invoker);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,20 +82,20 @@ public class CachingOperationInvokerAdvisorTests {
 | 
				
			||||||
	public void applyWhenTimeToLiveReturnsNullShouldNotAddAdvise() {
 | 
						public void applyWhenTimeToLiveReturnsNullShouldNotAddAdvise() {
 | 
				
			||||||
		OperationParameters parameters = getParameters("get");
 | 
							OperationParameters parameters = getParameters("get");
 | 
				
			||||||
		given(this.timeToLive.apply(any())).willReturn(null);
 | 
							given(this.timeToLive.apply(any())).willReturn(null);
 | 
				
			||||||
		OperationInvoker advised = this.advisor.apply("foo", OperationType.READ,
 | 
							OperationInvoker advised = this.advisor.apply(EndpointId.of("foo"),
 | 
				
			||||||
				parameters, this.invoker);
 | 
									OperationType.READ, parameters, this.invoker);
 | 
				
			||||||
		assertThat(advised).isSameAs(this.invoker);
 | 
							assertThat(advised).isSameAs(this.invoker);
 | 
				
			||||||
		verify(this.timeToLive).apply("foo");
 | 
							verify(this.timeToLive).apply(EndpointId.of("foo"));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void applyWhenTimeToLiveIsZeroShouldNotAddAdvise() {
 | 
						public void applyWhenTimeToLiveIsZeroShouldNotAddAdvise() {
 | 
				
			||||||
		OperationParameters parameters = getParameters("get");
 | 
							OperationParameters parameters = getParameters("get");
 | 
				
			||||||
		given(this.timeToLive.apply(any())).willReturn(0L);
 | 
							given(this.timeToLive.apply(any())).willReturn(0L);
 | 
				
			||||||
		OperationInvoker advised = this.advisor.apply("foo", OperationType.READ,
 | 
							OperationInvoker advised = this.advisor.apply(EndpointId.of("foo"),
 | 
				
			||||||
				parameters, this.invoker);
 | 
									OperationType.READ, parameters, this.invoker);
 | 
				
			||||||
		assertThat(advised).isSameAs(this.invoker);
 | 
							assertThat(advised).isSameAs(this.invoker);
 | 
				
			||||||
		verify(this.timeToLive).apply("foo");
 | 
							verify(this.timeToLive).apply(EndpointId.of("foo"));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
| 
						 | 
					@ -121,8 +122,8 @@ public class CachingOperationInvokerAdvisorTests {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private void assertAdviseIsApplied(OperationParameters parameters) {
 | 
						private void assertAdviseIsApplied(OperationParameters parameters) {
 | 
				
			||||||
		OperationInvoker advised = this.advisor.apply("foo", OperationType.READ,
 | 
							OperationInvoker advised = this.advisor.apply(EndpointId.of("foo"),
 | 
				
			||||||
				parameters, this.invoker);
 | 
									OperationType.READ, parameters, this.invoker);
 | 
				
			||||||
		assertThat(advised).isInstanceOf(CachingOperationInvoker.class);
 | 
							assertThat(advised).isInstanceOf(CachingOperationInvoker.class);
 | 
				
			||||||
		assertThat(ReflectionTestUtils.getField(advised, "invoker"))
 | 
							assertThat(ReflectionTestUtils.getField(advised, "invoker"))
 | 
				
			||||||
				.isEqualTo(this.invoker);
 | 
									.isEqualTo(this.invoker);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -190,9 +190,8 @@ public class JmxEndpointExporterTests {
 | 
				
			||||||
		@Override
 | 
							@Override
 | 
				
			||||||
		public ObjectName getObjectName(ExposableJmxEndpoint endpoint)
 | 
							public ObjectName getObjectName(ExposableJmxEndpoint endpoint)
 | 
				
			||||||
				throws MalformedObjectNameException {
 | 
									throws MalformedObjectNameException {
 | 
				
			||||||
			return (endpoint != null)
 | 
								return (endpoint != null) ? new ObjectName(
 | 
				
			||||||
					? new ObjectName("boot:type=Endpoint,name=" + endpoint.getId())
 | 
										"boot:type=Endpoint,name=" + endpoint.getEndpointId()) : null;
 | 
				
			||||||
					: null;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,6 +25,7 @@ import java.util.Map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.junit.Test;
 | 
					import org.junit.Test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.OperationType;
 | 
					import org.springframework.boot.actuate.endpoint.OperationType;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.DiscoveredOperationMethod;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.DiscoveredOperationMethod;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.invoke.OperationInvoker;
 | 
					import org.springframework.boot.actuate.endpoint.invoke.OperationInvoker;
 | 
				
			||||||
| 
						 | 
					@ -126,8 +127,8 @@ public class DiscoveredJmxOperationTests {
 | 
				
			||||||
		annotationAttributes.put("produces", "application/xml");
 | 
							annotationAttributes.put("produces", "application/xml");
 | 
				
			||||||
		DiscoveredOperationMethod operationMethod = new DiscoveredOperationMethod(method,
 | 
							DiscoveredOperationMethod operationMethod = new DiscoveredOperationMethod(method,
 | 
				
			||||||
				OperationType.READ, annotationAttributes);
 | 
									OperationType.READ, annotationAttributes);
 | 
				
			||||||
		DiscoveredJmxOperation operation = new DiscoveredJmxOperation("test",
 | 
							DiscoveredJmxOperation operation = new DiscoveredJmxOperation(
 | 
				
			||||||
				operationMethod, mock(OperationInvoker.class));
 | 
									EndpointId.of("test"), operationMethod, mock(OperationInvoker.class));
 | 
				
			||||||
		return operation;
 | 
							return operation;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,6 +28,7 @@ import org.junit.Rule;
 | 
				
			||||||
import org.junit.Test;
 | 
					import org.junit.Test;
 | 
				
			||||||
import org.junit.rules.ExpectedException;
 | 
					import org.junit.rules.ExpectedException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.DeleteOperation;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.DeleteOperation;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
 | 
				
			||||||
| 
						 | 
					@ -70,10 +71,10 @@ public class JmxEndpointDiscovererTests {
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void getEndpointsShouldDiscoverStandardEndpoints() {
 | 
						public void getEndpointsShouldDiscoverStandardEndpoints() {
 | 
				
			||||||
		load(TestEndpoint.class, (discoverer) -> {
 | 
							load(TestEndpoint.class, (discoverer) -> {
 | 
				
			||||||
			Map<String, ExposableJmxEndpoint> endpoints = discover(discoverer);
 | 
								Map<EndpointId, ExposableJmxEndpoint> endpoints = discover(discoverer);
 | 
				
			||||||
			assertThat(endpoints).containsOnlyKeys("test");
 | 
								assertThat(endpoints).containsOnlyKeys(EndpointId.of("test"));
 | 
				
			||||||
			Map<String, JmxOperation> operationByName = mapOperations(
 | 
								Map<String, JmxOperation> operationByName = mapOperations(
 | 
				
			||||||
					endpoints.get("test").getOperations());
 | 
										endpoints.get(EndpointId.of("test")).getOperations());
 | 
				
			||||||
			assertThat(operationByName).containsOnlyKeys("getAll", "getSomething",
 | 
								assertThat(operationByName).containsOnlyKeys("getAll", "getSomething",
 | 
				
			||||||
					"update", "deleteSomething");
 | 
										"update", "deleteSomething");
 | 
				
			||||||
			JmxOperation getAll = operationByName.get("getAll");
 | 
								JmxOperation getAll = operationByName.get("getAll");
 | 
				
			||||||
| 
						 | 
					@ -106,8 +107,9 @@ public class JmxEndpointDiscovererTests {
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void getEndpointsWhenHasFilteredEndpointShouldOnlyDiscoverJmxEndpoints() {
 | 
						public void getEndpointsWhenHasFilteredEndpointShouldOnlyDiscoverJmxEndpoints() {
 | 
				
			||||||
		load(MultipleEndpointsConfiguration.class, (discoverer) -> {
 | 
							load(MultipleEndpointsConfiguration.class, (discoverer) -> {
 | 
				
			||||||
			Map<String, ExposableJmxEndpoint> endpoints = discover(discoverer);
 | 
								Map<EndpointId, ExposableJmxEndpoint> endpoints = discover(discoverer);
 | 
				
			||||||
			assertThat(endpoints).containsOnlyKeys("test", "jmx");
 | 
								assertThat(endpoints).containsOnlyKeys(EndpointId.of("test"),
 | 
				
			||||||
 | 
										EndpointId.of("jmx"));
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -125,19 +127,19 @@ public class JmxEndpointDiscovererTests {
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void getEndpointsWhenHasJmxExtensionShouldOverrideStandardEndpoint() {
 | 
						public void getEndpointsWhenHasJmxExtensionShouldOverrideStandardEndpoint() {
 | 
				
			||||||
		load(OverriddenOperationJmxEndpointConfiguration.class, (discoverer) -> {
 | 
							load(OverriddenOperationJmxEndpointConfiguration.class, (discoverer) -> {
 | 
				
			||||||
			Map<String, ExposableJmxEndpoint> endpoints = discover(discoverer);
 | 
								Map<EndpointId, ExposableJmxEndpoint> endpoints = discover(discoverer);
 | 
				
			||||||
			assertThat(endpoints).containsOnlyKeys("test");
 | 
								assertThat(endpoints).containsOnlyKeys(EndpointId.of("test"));
 | 
				
			||||||
			assertJmxTestEndpoint(endpoints.get("test"));
 | 
								assertJmxTestEndpoint(endpoints.get(EndpointId.of("test")));
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void getEndpointsWhenHasJmxExtensionWithNewOperationAddsExtraOperation() {
 | 
						public void getEndpointsWhenHasJmxExtensionWithNewOperationAddsExtraOperation() {
 | 
				
			||||||
		load(AdditionalOperationJmxEndpointConfiguration.class, (discoverer) -> {
 | 
							load(AdditionalOperationJmxEndpointConfiguration.class, (discoverer) -> {
 | 
				
			||||||
			Map<String, ExposableJmxEndpoint> endpoints = discover(discoverer);
 | 
								Map<EndpointId, ExposableJmxEndpoint> endpoints = discover(discoverer);
 | 
				
			||||||
			assertThat(endpoints).containsOnlyKeys("test");
 | 
								assertThat(endpoints).containsOnlyKeys(EndpointId.of("test"));
 | 
				
			||||||
			Map<String, JmxOperation> operationByName = mapOperations(
 | 
								Map<String, JmxOperation> operationByName = mapOperations(
 | 
				
			||||||
					endpoints.get("test").getOperations());
 | 
										endpoints.get(EndpointId.of("test")).getOperations());
 | 
				
			||||||
			assertThat(operationByName).containsOnlyKeys("getAll", "getSomething",
 | 
								assertThat(operationByName).containsOnlyKeys("getAll", "getSomething",
 | 
				
			||||||
					"update", "deleteSomething", "getAnother");
 | 
										"update", "deleteSomething", "getAnother");
 | 
				
			||||||
			JmxOperation getAnother = operationByName.get("getAnother");
 | 
								JmxOperation getAnother = operationByName.get("getAnother");
 | 
				
			||||||
| 
						 | 
					@ -150,10 +152,10 @@ public class JmxEndpointDiscovererTests {
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void getEndpointsWhenHasCacheWithTtlShouldCacheReadOperationWithTtlValue() {
 | 
						public void getEndpointsWhenHasCacheWithTtlShouldCacheReadOperationWithTtlValue() {
 | 
				
			||||||
		load(TestEndpoint.class, (id) -> 500L, (discoverer) -> {
 | 
							load(TestEndpoint.class, (id) -> 500L, (discoverer) -> {
 | 
				
			||||||
			Map<String, ExposableJmxEndpoint> endpoints = discover(discoverer);
 | 
								Map<EndpointId, ExposableJmxEndpoint> endpoints = discover(discoverer);
 | 
				
			||||||
			assertThat(endpoints).containsOnlyKeys("test");
 | 
								assertThat(endpoints).containsOnlyKeys(EndpointId.of("test"));
 | 
				
			||||||
			Map<String, JmxOperation> operationByName = mapOperations(
 | 
								Map<String, JmxOperation> operationByName = mapOperations(
 | 
				
			||||||
					endpoints.get("test").getOperations());
 | 
										endpoints.get(EndpointId.of("test")).getOperations());
 | 
				
			||||||
			assertThat(operationByName).containsOnlyKeys("getAll", "getSomething",
 | 
								assertThat(operationByName).containsOnlyKeys("getAll", "getSomething",
 | 
				
			||||||
					"update", "deleteSomething");
 | 
										"update", "deleteSomething");
 | 
				
			||||||
			JmxOperation getAll = operationByName.get("getAll");
 | 
								JmxOperation getAll = operationByName.get("getAll");
 | 
				
			||||||
| 
						 | 
					@ -167,10 +169,11 @@ public class JmxEndpointDiscovererTests {
 | 
				
			||||||
	public void getEndpointsShouldCacheReadOperations() {
 | 
						public void getEndpointsShouldCacheReadOperations() {
 | 
				
			||||||
		load(AdditionalOperationJmxEndpointConfiguration.class, (id) -> 500L,
 | 
							load(AdditionalOperationJmxEndpointConfiguration.class, (id) -> 500L,
 | 
				
			||||||
				(discoverer) -> {
 | 
									(discoverer) -> {
 | 
				
			||||||
					Map<String, ExposableJmxEndpoint> endpoints = discover(discoverer);
 | 
										Map<EndpointId, ExposableJmxEndpoint> endpoints = discover(
 | 
				
			||||||
					assertThat(endpoints).containsOnlyKeys("test");
 | 
												discoverer);
 | 
				
			||||||
 | 
										assertThat(endpoints).containsOnlyKeys(EndpointId.of("test"));
 | 
				
			||||||
					Map<String, JmxOperation> operationByName = mapOperations(
 | 
										Map<String, JmxOperation> operationByName = mapOperations(
 | 
				
			||||||
							endpoints.get("test").getOperations());
 | 
												endpoints.get(EndpointId.of("test")).getOperations());
 | 
				
			||||||
					assertThat(operationByName).containsOnlyKeys("getAll", "getSomething",
 | 
										assertThat(operationByName).containsOnlyKeys("getAll", "getSomething",
 | 
				
			||||||
							"update", "deleteSomething", "getAnother");
 | 
												"update", "deleteSomething", "getAnother");
 | 
				
			||||||
					JmxOperation getAll = operationByName.get("getAll");
 | 
										JmxOperation getAll = operationByName.get("getAll");
 | 
				
			||||||
| 
						 | 
					@ -285,10 +288,11 @@ public class JmxEndpointDiscovererTests {
 | 
				
			||||||
		assertThat(parameter.getType()).isEqualTo(type);
 | 
							assertThat(parameter.getType()).isEqualTo(type);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private Map<String, ExposableJmxEndpoint> discover(JmxEndpointDiscoverer discoverer) {
 | 
						private Map<EndpointId, ExposableJmxEndpoint> discover(
 | 
				
			||||||
		Map<String, ExposableJmxEndpoint> byId = new HashMap<>();
 | 
								JmxEndpointDiscoverer discoverer) {
 | 
				
			||||||
 | 
							Map<EndpointId, ExposableJmxEndpoint> byId = new HashMap<>();
 | 
				
			||||||
		discoverer.getEndpoints()
 | 
							discoverer.getEndpoints()
 | 
				
			||||||
				.forEach((endpoint) -> byId.put(endpoint.getId(), endpoint));
 | 
									.forEach((endpoint) -> byId.put(endpoint.getEndpointId(), endpoint));
 | 
				
			||||||
		return byId;
 | 
							return byId;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -302,7 +306,7 @@ public class JmxEndpointDiscovererTests {
 | 
				
			||||||
		load(configuration, (id) -> null, consumer);
 | 
							load(configuration, (id) -> null, consumer);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private void load(Class<?> configuration, Function<String, Long> timeToLive,
 | 
						private void load(Class<?> configuration, Function<EndpointId, Long> timeToLive,
 | 
				
			||||||
			Consumer<JmxEndpointDiscoverer> consumer) {
 | 
								Consumer<JmxEndpointDiscoverer> consumer) {
 | 
				
			||||||
		try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
 | 
							try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
 | 
				
			||||||
				configuration)) {
 | 
									configuration)) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,7 @@ import java.util.Map;
 | 
				
			||||||
import org.assertj.core.api.Condition;
 | 
					import org.assertj.core.api.Condition;
 | 
				
			||||||
import org.junit.Test;
 | 
					import org.junit.Test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.OperationType;
 | 
					import org.springframework.boot.actuate.endpoint.OperationType;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.web.annotation.ExposableControllerEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.web.annotation.ExposableControllerEndpoint;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,7 +63,7 @@ public class EndpointLinksResolverTests {
 | 
				
			||||||
		operations.add(operationWithPath("/alpha", "alpha"));
 | 
							operations.add(operationWithPath("/alpha", "alpha"));
 | 
				
			||||||
		operations.add(operationWithPath("/alpha/{name}", "alpha-name"));
 | 
							operations.add(operationWithPath("/alpha/{name}", "alpha-name"));
 | 
				
			||||||
		ExposableWebEndpoint endpoint = mock(ExposableWebEndpoint.class);
 | 
							ExposableWebEndpoint endpoint = mock(ExposableWebEndpoint.class);
 | 
				
			||||||
		given(endpoint.getId()).willReturn("alpha");
 | 
							given(endpoint.getEndpointId()).willReturn(EndpointId.of("alpha"));
 | 
				
			||||||
		given(endpoint.isEnableByDefault()).willReturn(true);
 | 
							given(endpoint.isEnableByDefault()).willReturn(true);
 | 
				
			||||||
		given(endpoint.getOperations()).willReturn(operations);
 | 
							given(endpoint.getOperations()).willReturn(operations);
 | 
				
			||||||
		String requestUrl = "https://api.example.com/actuator";
 | 
							String requestUrl = "https://api.example.com/actuator";
 | 
				
			||||||
| 
						 | 
					@ -80,7 +81,7 @@ public class EndpointLinksResolverTests {
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void resolvedLinksContainsALinkForServletEndpoint() {
 | 
						public void resolvedLinksContainsALinkForServletEndpoint() {
 | 
				
			||||||
		ExposableServletEndpoint servletEndpoint = mock(ExposableServletEndpoint.class);
 | 
							ExposableServletEndpoint servletEndpoint = mock(ExposableServletEndpoint.class);
 | 
				
			||||||
		given(servletEndpoint.getId()).willReturn("alpha");
 | 
							given(servletEndpoint.getEndpointId()).willReturn(EndpointId.of("alpha"));
 | 
				
			||||||
		given(servletEndpoint.isEnableByDefault()).willReturn(true);
 | 
							given(servletEndpoint.isEnableByDefault()).willReturn(true);
 | 
				
			||||||
		given(servletEndpoint.getRootPath()).willReturn("alpha");
 | 
							given(servletEndpoint.getRootPath()).willReturn("alpha");
 | 
				
			||||||
		String requestUrl = "https://api.example.com/actuator";
 | 
							String requestUrl = "https://api.example.com/actuator";
 | 
				
			||||||
| 
						 | 
					@ -97,7 +98,7 @@ public class EndpointLinksResolverTests {
 | 
				
			||||||
	public void resolvedLinksContainsALinkForControllerEndpoint() {
 | 
						public void resolvedLinksContainsALinkForControllerEndpoint() {
 | 
				
			||||||
		ExposableControllerEndpoint controllerEndpoint = mock(
 | 
							ExposableControllerEndpoint controllerEndpoint = mock(
 | 
				
			||||||
				ExposableControllerEndpoint.class);
 | 
									ExposableControllerEndpoint.class);
 | 
				
			||||||
		given(controllerEndpoint.getId()).willReturn("alpha");
 | 
							given(controllerEndpoint.getEndpointId()).willReturn(EndpointId.of("alpha"));
 | 
				
			||||||
		given(controllerEndpoint.isEnableByDefault()).willReturn(true);
 | 
							given(controllerEndpoint.isEnableByDefault()).willReturn(true);
 | 
				
			||||||
		given(controllerEndpoint.getRootPath()).willReturn("alpha");
 | 
							given(controllerEndpoint.getRootPath()).willReturn("alpha");
 | 
				
			||||||
		String requestUrl = "https://api.example.com/actuator";
 | 
							String requestUrl = "https://api.example.com/actuator";
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,7 @@ import org.junit.Rule;
 | 
				
			||||||
import org.junit.Test;
 | 
					import org.junit.Test;
 | 
				
			||||||
import org.junit.rules.ExpectedException;
 | 
					import org.junit.rules.ExpectedException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.EndpointsSupplier;
 | 
					import org.springframework.boot.actuate.endpoint.EndpointsSupplier;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.Operation;
 | 
					import org.springframework.boot.actuate.endpoint.Operation;
 | 
				
			||||||
| 
						 | 
					@ -60,38 +61,41 @@ public class PathMappedEndpointsTests {
 | 
				
			||||||
	public void iteratorShouldReturnPathMappedEndpoints() {
 | 
						public void iteratorShouldReturnPathMappedEndpoints() {
 | 
				
			||||||
		PathMappedEndpoints mapped = createTestMapped(null);
 | 
							PathMappedEndpoints mapped = createTestMapped(null);
 | 
				
			||||||
		assertThat(mapped).hasSize(2);
 | 
							assertThat(mapped).hasSize(2);
 | 
				
			||||||
		assertThat(mapped).extracting("id").containsExactly("e2", "e3");
 | 
							assertThat(mapped).extracting("endpointId").containsExactly(EndpointId.of("e2"),
 | 
				
			||||||
 | 
									EndpointId.of("e3"));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void streamShouldReturnPathMappedEndpoints() {
 | 
						public void streamShouldReturnPathMappedEndpoints() {
 | 
				
			||||||
		PathMappedEndpoints mapped = createTestMapped(null);
 | 
							PathMappedEndpoints mapped = createTestMapped(null);
 | 
				
			||||||
		assertThat(mapped.stream()).hasSize(2);
 | 
							assertThat(mapped.stream()).hasSize(2);
 | 
				
			||||||
		assertThat(mapped.stream()).extracting("id").containsExactly("e2", "e3");
 | 
							assertThat(mapped.stream()).extracting("endpointId")
 | 
				
			||||||
 | 
									.containsExactly(EndpointId.of("e2"), EndpointId.of("e3"));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void getRootPathWhenContainsIdShouldReturnRootPath() {
 | 
						public void getRootPathWhenContainsIdShouldReturnRootPath() {
 | 
				
			||||||
		PathMappedEndpoints mapped = createTestMapped(null);
 | 
							PathMappedEndpoints mapped = createTestMapped(null);
 | 
				
			||||||
		assertThat(mapped.getRootPath("e2")).isEqualTo("p2");
 | 
							assertThat(mapped.getRootPath(EndpointId.of("e2"))).isEqualTo("p2");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void getRootPathWhenMissingIdShouldReturnNull() {
 | 
						public void getRootPathWhenMissingIdShouldReturnNull() {
 | 
				
			||||||
		PathMappedEndpoints mapped = createTestMapped(null);
 | 
							PathMappedEndpoints mapped = createTestMapped(null);
 | 
				
			||||||
		assertThat(mapped.getRootPath("xx")).isNull();
 | 
							assertThat(mapped.getRootPath(EndpointId.of("xx"))).isNull();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void getPathWhenContainsIdShouldReturnRootPath() {
 | 
						public void getPathWhenContainsIdShouldReturnRootPath() {
 | 
				
			||||||
		assertThat(createTestMapped(null).getPath("e2")).isEqualTo("/p2");
 | 
							assertThat(createTestMapped(null).getPath(EndpointId.of("e2"))).isEqualTo("/p2");
 | 
				
			||||||
		assertThat(createTestMapped("/x").getPath("e2")).isEqualTo("/x/p2");
 | 
							assertThat(createTestMapped("/x").getPath(EndpointId.of("e2")))
 | 
				
			||||||
 | 
									.isEqualTo("/x/p2");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void getPathWhenMissingIdShouldReturnNull() {
 | 
						public void getPathWhenMissingIdShouldReturnNull() {
 | 
				
			||||||
		PathMappedEndpoints mapped = createTestMapped(null);
 | 
							PathMappedEndpoints mapped = createTestMapped(null);
 | 
				
			||||||
		assertThat(mapped.getRootPath("xx")).isNull();
 | 
							assertThat(mapped.getPath(EndpointId.of("xx"))).isNull();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
| 
						 | 
					@ -110,34 +114,34 @@ public class PathMappedEndpointsTests {
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void getEndpointWhenContainsIdShouldReturnPathMappedEndpoint() {
 | 
						public void getEndpointWhenContainsIdShouldReturnPathMappedEndpoint() {
 | 
				
			||||||
		PathMappedEndpoints mapped = createTestMapped(null);
 | 
							PathMappedEndpoints mapped = createTestMapped(null);
 | 
				
			||||||
		assertThat(mapped.getEndpoint("e2").getRootPath()).isEqualTo("p2");
 | 
							assertThat(mapped.getEndpoint(EndpointId.of("e2")).getRootPath()).isEqualTo("p2");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void getEndpointWhenMissingIdShouldReturnNull() {
 | 
						public void getEndpointWhenMissingIdShouldReturnNull() {
 | 
				
			||||||
		PathMappedEndpoints mapped = createTestMapped(null);
 | 
							PathMappedEndpoints mapped = createTestMapped(null);
 | 
				
			||||||
		assertThat(mapped.getEndpoint("xx")).isNull();
 | 
							assertThat(mapped.getEndpoint(EndpointId.of("xx"))).isNull();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private PathMappedEndpoints createTestMapped(String basePath) {
 | 
						private PathMappedEndpoints createTestMapped(String basePath) {
 | 
				
			||||||
		List<ExposableEndpoint<?>> endpoints = new ArrayList<>();
 | 
							List<ExposableEndpoint<?>> endpoints = new ArrayList<>();
 | 
				
			||||||
		endpoints.add(mockEndpoint("e1"));
 | 
							endpoints.add(mockEndpoint(EndpointId.of("e1")));
 | 
				
			||||||
		endpoints.add(mockEndpoint("e2", "p2"));
 | 
							endpoints.add(mockEndpoint(EndpointId.of("e2"), "p2"));
 | 
				
			||||||
		endpoints.add(mockEndpoint("e3", "p3"));
 | 
							endpoints.add(mockEndpoint(EndpointId.of("e3"), "p3"));
 | 
				
			||||||
		endpoints.add(mockEndpoint("e4"));
 | 
							endpoints.add(mockEndpoint(EndpointId.of("e4")));
 | 
				
			||||||
		return new PathMappedEndpoints(basePath, () -> endpoints);
 | 
							return new PathMappedEndpoints(basePath, () -> endpoints);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private TestPathMappedEndpoint mockEndpoint(String id, String rootPath) {
 | 
						private TestPathMappedEndpoint mockEndpoint(EndpointId id, String rootPath) {
 | 
				
			||||||
		TestPathMappedEndpoint endpoint = mock(TestPathMappedEndpoint.class);
 | 
							TestPathMappedEndpoint endpoint = mock(TestPathMappedEndpoint.class);
 | 
				
			||||||
		given(endpoint.getId()).willReturn(id);
 | 
							given(endpoint.getEndpointId()).willReturn(id);
 | 
				
			||||||
		given(endpoint.getRootPath()).willReturn(rootPath);
 | 
							given(endpoint.getRootPath()).willReturn(rootPath);
 | 
				
			||||||
		return endpoint;
 | 
							return endpoint;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private TestEndpoint mockEndpoint(String id) {
 | 
						private TestEndpoint mockEndpoint(EndpointId id) {
 | 
				
			||||||
		TestEndpoint endpoint = mock(TestEndpoint.class);
 | 
							TestEndpoint endpoint = mock(TestEndpoint.class);
 | 
				
			||||||
		given(endpoint.getId()).willReturn(id);
 | 
							given(endpoint.getEndpointId()).willReturn(id);
 | 
				
			||||||
		return endpoint;
 | 
							return endpoint;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,6 +35,8 @@ import org.mockito.Captor;
 | 
				
			||||||
import org.mockito.Mock;
 | 
					import org.mockito.Mock;
 | 
				
			||||||
import org.mockito.MockitoAnnotations;
 | 
					import org.mockito.MockitoAnnotations;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
					import static org.assertj.core.api.Assertions.assertThat;
 | 
				
			||||||
import static org.mockito.ArgumentMatchers.any;
 | 
					import static org.mockito.ArgumentMatchers.any;
 | 
				
			||||||
import static org.mockito.ArgumentMatchers.eq;
 | 
					import static org.mockito.ArgumentMatchers.eq;
 | 
				
			||||||
| 
						 | 
					@ -124,7 +126,7 @@ public class ServletEndpointRegistrarTests {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private ExposableServletEndpoint mockEndpoint(EndpointServlet endpointServlet) {
 | 
						private ExposableServletEndpoint mockEndpoint(EndpointServlet endpointServlet) {
 | 
				
			||||||
		ExposableServletEndpoint endpoint = mock(ExposableServletEndpoint.class);
 | 
							ExposableServletEndpoint endpoint = mock(ExposableServletEndpoint.class);
 | 
				
			||||||
		given(endpoint.getId()).willReturn("test");
 | 
							given(endpoint.getEndpointId()).willReturn(EndpointId.of("test"));
 | 
				
			||||||
		given(endpoint.getEndpointServlet()).willReturn(endpointServlet);
 | 
							given(endpoint.getEndpointServlet()).willReturn(endpointServlet);
 | 
				
			||||||
		given(endpoint.getRootPath()).willReturn("test");
 | 
							given(endpoint.getRootPath()).willReturn("test");
 | 
				
			||||||
		return endpoint;
 | 
							return endpoint;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,6 +26,7 @@ import org.junit.Rule;
 | 
				
			||||||
import org.junit.Test;
 | 
					import org.junit.Test;
 | 
				
			||||||
import org.junit.rules.ExpectedException;
 | 
					import org.junit.rules.ExpectedException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.DiscoveredEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.DiscoveredEndpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
				
			||||||
| 
						 | 
					@ -70,7 +71,8 @@ public class ControllerEndpointDiscovererTests {
 | 
				
			||||||
							.getEndpoints();
 | 
												.getEndpoints();
 | 
				
			||||||
					assertThat(endpoints).hasSize(1);
 | 
										assertThat(endpoints).hasSize(1);
 | 
				
			||||||
					ExposableControllerEndpoint endpoint = endpoints.iterator().next();
 | 
										ExposableControllerEndpoint endpoint = endpoints.iterator().next();
 | 
				
			||||||
					assertThat(endpoint.getId()).isEqualTo("testcontroller");
 | 
										assertThat(endpoint.getEndpointId())
 | 
				
			||||||
 | 
												.isEqualTo(EndpointId.of("testcontroller"));
 | 
				
			||||||
					assertThat(endpoint.getController())
 | 
										assertThat(endpoint.getController())
 | 
				
			||||||
							.isInstanceOf(TestControllerEndpoint.class);
 | 
												.isInstanceOf(TestControllerEndpoint.class);
 | 
				
			||||||
					assertThat(endpoint).isInstanceOf(DiscoveredEndpoint.class);
 | 
										assertThat(endpoint).isInstanceOf(DiscoveredEndpoint.class);
 | 
				
			||||||
| 
						 | 
					@ -87,7 +89,8 @@ public class ControllerEndpointDiscovererTests {
 | 
				
			||||||
							.getEndpoints();
 | 
												.getEndpoints();
 | 
				
			||||||
					assertThat(endpoints).hasSize(1);
 | 
										assertThat(endpoints).hasSize(1);
 | 
				
			||||||
					ExposableControllerEndpoint endpoint = endpoints.iterator().next();
 | 
										ExposableControllerEndpoint endpoint = endpoints.iterator().next();
 | 
				
			||||||
					assertThat(endpoint.getId()).isEqualTo("testcontroller");
 | 
										assertThat(endpoint.getEndpointId())
 | 
				
			||||||
 | 
												.isEqualTo(EndpointId.of("testcontroller"));
 | 
				
			||||||
					assertThat(endpoint.getController())
 | 
										assertThat(endpoint.getController())
 | 
				
			||||||
							.isInstanceOf(TestProxyControllerEndpoint.class);
 | 
												.isInstanceOf(TestProxyControllerEndpoint.class);
 | 
				
			||||||
					assertThat(endpoint).isInstanceOf(DiscoveredEndpoint.class);
 | 
										assertThat(endpoint).isInstanceOf(DiscoveredEndpoint.class);
 | 
				
			||||||
| 
						 | 
					@ -102,7 +105,8 @@ public class ControllerEndpointDiscovererTests {
 | 
				
			||||||
							.getEndpoints();
 | 
												.getEndpoints();
 | 
				
			||||||
					assertThat(endpoints).hasSize(1);
 | 
										assertThat(endpoints).hasSize(1);
 | 
				
			||||||
					ExposableControllerEndpoint endpoint = endpoints.iterator().next();
 | 
										ExposableControllerEndpoint endpoint = endpoints.iterator().next();
 | 
				
			||||||
					assertThat(endpoint.getId()).isEqualTo("testrestcontroller");
 | 
										assertThat(endpoint.getEndpointId())
 | 
				
			||||||
 | 
												.isEqualTo(EndpointId.of("testrestcontroller"));
 | 
				
			||||||
					assertThat(endpoint.getController())
 | 
										assertThat(endpoint.getController())
 | 
				
			||||||
							.isInstanceOf(TestRestControllerEndpoint.class);
 | 
												.isInstanceOf(TestRestControllerEndpoint.class);
 | 
				
			||||||
				}));
 | 
									}));
 | 
				
			||||||
| 
						 | 
					@ -118,7 +122,8 @@ public class ControllerEndpointDiscovererTests {
 | 
				
			||||||
							.getEndpoints();
 | 
												.getEndpoints();
 | 
				
			||||||
					assertThat(endpoints).hasSize(1);
 | 
										assertThat(endpoints).hasSize(1);
 | 
				
			||||||
					ExposableControllerEndpoint endpoint = endpoints.iterator().next();
 | 
										ExposableControllerEndpoint endpoint = endpoints.iterator().next();
 | 
				
			||||||
					assertThat(endpoint.getId()).isEqualTo("testrestcontroller");
 | 
										assertThat(endpoint.getEndpointId())
 | 
				
			||||||
 | 
												.isEqualTo(EndpointId.of("testrestcontroller"));
 | 
				
			||||||
					assertThat(endpoint.getController())
 | 
										assertThat(endpoint.getController())
 | 
				
			||||||
							.isInstanceOf(TestProxyRestControllerEndpoint.class);
 | 
												.isInstanceOf(TestProxyRestControllerEndpoint.class);
 | 
				
			||||||
					assertThat(endpoint).isInstanceOf(DiscoveredEndpoint.class);
 | 
										assertThat(endpoint).isInstanceOf(DiscoveredEndpoint.class);
 | 
				
			||||||
| 
						 | 
					@ -131,9 +136,11 @@ public class ControllerEndpointDiscovererTests {
 | 
				
			||||||
				.run(assertDiscoverer((discoverer) -> {
 | 
									.run(assertDiscoverer((discoverer) -> {
 | 
				
			||||||
					Collection<ExposableControllerEndpoint> endpoints = discoverer
 | 
										Collection<ExposableControllerEndpoint> endpoints = discoverer
 | 
				
			||||||
							.getEndpoints();
 | 
												.getEndpoints();
 | 
				
			||||||
					List<String> ids = endpoints.stream().map(ExposableEndpoint::getId)
 | 
										List<EndpointId> ids = endpoints.stream()
 | 
				
			||||||
 | 
												.map(ExposableEndpoint::getEndpointId)
 | 
				
			||||||
							.collect(Collectors.toList());
 | 
												.collect(Collectors.toList());
 | 
				
			||||||
					assertThat(ids).containsOnly("testcontroller", "testrestcontroller");
 | 
										assertThat(ids).containsOnly(EndpointId.of("testcontroller"),
 | 
				
			||||||
 | 
												EndpointId.of("testrestcontroller"));
 | 
				
			||||||
				}));
 | 
									}));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,6 +33,7 @@ import org.junit.Rule;
 | 
				
			||||||
import org.junit.Test;
 | 
					import org.junit.Test;
 | 
				
			||||||
import org.junit.rules.ExpectedException;
 | 
					import org.junit.rules.ExpectedException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.DiscoveredEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.DiscoveredEndpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
				
			||||||
| 
						 | 
					@ -79,7 +80,8 @@ public class ServletEndpointDiscovererTests {
 | 
				
			||||||
							.getEndpoints();
 | 
												.getEndpoints();
 | 
				
			||||||
					assertThat(endpoints).hasSize(1);
 | 
										assertThat(endpoints).hasSize(1);
 | 
				
			||||||
					ExposableServletEndpoint endpoint = endpoints.iterator().next();
 | 
										ExposableServletEndpoint endpoint = endpoints.iterator().next();
 | 
				
			||||||
					assertThat(endpoint.getId()).isEqualTo("testservlet");
 | 
										assertThat(endpoint.getEndpointId())
 | 
				
			||||||
 | 
												.isEqualTo(EndpointId.of("testservlet"));
 | 
				
			||||||
					assertThat(endpoint.getEndpointServlet()).isNotNull();
 | 
										assertThat(endpoint.getEndpointServlet()).isNotNull();
 | 
				
			||||||
					assertThat(endpoint).isInstanceOf(DiscoveredEndpoint.class);
 | 
										assertThat(endpoint).isInstanceOf(DiscoveredEndpoint.class);
 | 
				
			||||||
				}));
 | 
									}));
 | 
				
			||||||
| 
						 | 
					@ -95,7 +97,8 @@ public class ServletEndpointDiscovererTests {
 | 
				
			||||||
							.getEndpoints();
 | 
												.getEndpoints();
 | 
				
			||||||
					assertThat(endpoints).hasSize(1);
 | 
										assertThat(endpoints).hasSize(1);
 | 
				
			||||||
					ExposableServletEndpoint endpoint = endpoints.iterator().next();
 | 
										ExposableServletEndpoint endpoint = endpoints.iterator().next();
 | 
				
			||||||
					assertThat(endpoint.getId()).isEqualTo("testservlet");
 | 
										assertThat(endpoint.getEndpointId())
 | 
				
			||||||
 | 
												.isEqualTo(EndpointId.of("testservlet"));
 | 
				
			||||||
					assertThat(endpoint.getEndpointServlet()).isNotNull();
 | 
										assertThat(endpoint.getEndpointServlet()).isNotNull();
 | 
				
			||||||
					assertThat(endpoint).isInstanceOf(DiscoveredEndpoint.class);
 | 
										assertThat(endpoint).isInstanceOf(DiscoveredEndpoint.class);
 | 
				
			||||||
				}));
 | 
									}));
 | 
				
			||||||
| 
						 | 
					@ -107,9 +110,10 @@ public class ServletEndpointDiscovererTests {
 | 
				
			||||||
				.run(assertDiscoverer((discoverer) -> {
 | 
									.run(assertDiscoverer((discoverer) -> {
 | 
				
			||||||
					Collection<ExposableServletEndpoint> endpoints = discoverer
 | 
										Collection<ExposableServletEndpoint> endpoints = discoverer
 | 
				
			||||||
							.getEndpoints();
 | 
												.getEndpoints();
 | 
				
			||||||
					List<String> ids = endpoints.stream().map(ExposableEndpoint::getId)
 | 
										List<EndpointId> ids = endpoints.stream()
 | 
				
			||||||
 | 
												.map(ExposableEndpoint::getEndpointId)
 | 
				
			||||||
							.collect(Collectors.toList());
 | 
												.collect(Collectors.toList());
 | 
				
			||||||
					assertThat(ids).containsOnly("testservlet");
 | 
										assertThat(ids).containsOnly(EndpointId.of("testservlet"));
 | 
				
			||||||
				}));
 | 
									}));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,6 +33,7 @@ import org.junit.Rule;
 | 
				
			||||||
import org.junit.Test;
 | 
					import org.junit.Test;
 | 
				
			||||||
import org.junit.rules.ExpectedException;
 | 
					import org.junit.rules.ExpectedException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.DeleteOperation;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.DeleteOperation;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
 | 
					import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
 | 
				
			||||||
| 
						 | 
					@ -91,19 +92,19 @@ public class WebEndpointDiscovererTests {
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void getEndpointsWhenHasFilteredEndpointShouldOnlyDiscoverWebEndpoints() {
 | 
						public void getEndpointsWhenHasFilteredEndpointShouldOnlyDiscoverWebEndpoints() {
 | 
				
			||||||
		load(MultipleEndpointsConfiguration.class, (discoverer) -> {
 | 
							load(MultipleEndpointsConfiguration.class, (discoverer) -> {
 | 
				
			||||||
			Map<String, ExposableWebEndpoint> endpoints = mapEndpoints(
 | 
								Map<EndpointId, ExposableWebEndpoint> endpoints = mapEndpoints(
 | 
				
			||||||
					discoverer.getEndpoints());
 | 
										discoverer.getEndpoints());
 | 
				
			||||||
			assertThat(endpoints).containsOnlyKeys("test");
 | 
								assertThat(endpoints).containsOnlyKeys(EndpointId.of("test"));
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void getEndpointsWhenHasWebExtensionShouldOverrideStandardEndpoint() {
 | 
						public void getEndpointsWhenHasWebExtensionShouldOverrideStandardEndpoint() {
 | 
				
			||||||
		load(OverriddenOperationWebEndpointExtensionConfiguration.class, (discoverer) -> {
 | 
							load(OverriddenOperationWebEndpointExtensionConfiguration.class, (discoverer) -> {
 | 
				
			||||||
			Map<String, ExposableWebEndpoint> endpoints = mapEndpoints(
 | 
								Map<EndpointId, ExposableWebEndpoint> endpoints = mapEndpoints(
 | 
				
			||||||
					discoverer.getEndpoints());
 | 
										discoverer.getEndpoints());
 | 
				
			||||||
			assertThat(endpoints).containsOnlyKeys("test");
 | 
								assertThat(endpoints).containsOnlyKeys(EndpointId.of("test"));
 | 
				
			||||||
			ExposableWebEndpoint endpoint = endpoints.get("test");
 | 
								ExposableWebEndpoint endpoint = endpoints.get(EndpointId.of("test"));
 | 
				
			||||||
			assertThat(requestPredicates(endpoint)).has(
 | 
								assertThat(requestPredicates(endpoint)).has(
 | 
				
			||||||
					requestPredicates(path("test").httpMethod(WebEndpointHttpMethod.GET)
 | 
										requestPredicates(path("test").httpMethod(WebEndpointHttpMethod.GET)
 | 
				
			||||||
							.consumes().produces("application/json")));
 | 
												.consumes().produces("application/json")));
 | 
				
			||||||
| 
						 | 
					@ -113,10 +114,10 @@ public class WebEndpointDiscovererTests {
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void getEndpointsWhenExtensionAddsOperationShouldHaveBothOperations() {
 | 
						public void getEndpointsWhenExtensionAddsOperationShouldHaveBothOperations() {
 | 
				
			||||||
		load(AdditionalOperationWebEndpointConfiguration.class, (discoverer) -> {
 | 
							load(AdditionalOperationWebEndpointConfiguration.class, (discoverer) -> {
 | 
				
			||||||
			Map<String, ExposableWebEndpoint> endpoints = mapEndpoints(
 | 
								Map<EndpointId, ExposableWebEndpoint> endpoints = mapEndpoints(
 | 
				
			||||||
					discoverer.getEndpoints());
 | 
										discoverer.getEndpoints());
 | 
				
			||||||
			assertThat(endpoints).containsOnlyKeys("test");
 | 
								assertThat(endpoints).containsOnlyKeys(EndpointId.of("test"));
 | 
				
			||||||
			ExposableWebEndpoint endpoint = endpoints.get("test");
 | 
								ExposableWebEndpoint endpoint = endpoints.get(EndpointId.of("test"));
 | 
				
			||||||
			assertThat(requestPredicates(endpoint)).has(requestPredicates(
 | 
								assertThat(requestPredicates(endpoint)).has(requestPredicates(
 | 
				
			||||||
					path("test").httpMethod(WebEndpointHttpMethod.GET).consumes()
 | 
										path("test").httpMethod(WebEndpointHttpMethod.GET).consumes()
 | 
				
			||||||
							.produces("application/json"),
 | 
												.produces("application/json"),
 | 
				
			||||||
| 
						 | 
					@ -128,10 +129,10 @@ public class WebEndpointDiscovererTests {
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void getEndpointsWhenPredicateForWriteOperationThatReturnsVoidShouldHaveNoProducedMediaTypes() {
 | 
						public void getEndpointsWhenPredicateForWriteOperationThatReturnsVoidShouldHaveNoProducedMediaTypes() {
 | 
				
			||||||
		load(VoidWriteOperationEndpointConfiguration.class, (discoverer) -> {
 | 
							load(VoidWriteOperationEndpointConfiguration.class, (discoverer) -> {
 | 
				
			||||||
			Map<String, ExposableWebEndpoint> endpoints = mapEndpoints(
 | 
								Map<EndpointId, ExposableWebEndpoint> endpoints = mapEndpoints(
 | 
				
			||||||
					discoverer.getEndpoints());
 | 
										discoverer.getEndpoints());
 | 
				
			||||||
			assertThat(endpoints).containsOnlyKeys("voidwrite");
 | 
								assertThat(endpoints).containsOnlyKeys(EndpointId.of("voidwrite"));
 | 
				
			||||||
			ExposableWebEndpoint endpoint = endpoints.get("voidwrite");
 | 
								ExposableWebEndpoint endpoint = endpoints.get(EndpointId.of("voidwrite"));
 | 
				
			||||||
			assertThat(requestPredicates(endpoint)).has(requestPredicates(
 | 
								assertThat(requestPredicates(endpoint)).has(requestPredicates(
 | 
				
			||||||
					path("voidwrite").httpMethod(WebEndpointHttpMethod.POST).produces()
 | 
										path("voidwrite").httpMethod(WebEndpointHttpMethod.POST).produces()
 | 
				
			||||||
							.consumes("application/json")));
 | 
												.consumes("application/json")));
 | 
				
			||||||
| 
						 | 
					@ -191,10 +192,10 @@ public class WebEndpointDiscovererTests {
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void getEndpointsWhenHasCacheWithTtlShouldCacheReadOperationWithTtlValue() {
 | 
						public void getEndpointsWhenHasCacheWithTtlShouldCacheReadOperationWithTtlValue() {
 | 
				
			||||||
		load((id) -> 500L, (id) -> id, TestEndpointConfiguration.class, (discoverer) -> {
 | 
							load((id) -> 500L, (id) -> id, TestEndpointConfiguration.class, (discoverer) -> {
 | 
				
			||||||
			Map<String, ExposableWebEndpoint> endpoints = mapEndpoints(
 | 
								Map<EndpointId, ExposableWebEndpoint> endpoints = mapEndpoints(
 | 
				
			||||||
					discoverer.getEndpoints());
 | 
										discoverer.getEndpoints());
 | 
				
			||||||
			assertThat(endpoints).containsOnlyKeys("test");
 | 
								assertThat(endpoints).containsOnlyKeys(EndpointId.of("test"));
 | 
				
			||||||
			ExposableWebEndpoint endpoint = endpoints.get("test");
 | 
								ExposableWebEndpoint endpoint = endpoints.get(EndpointId.of("test"));
 | 
				
			||||||
			assertThat(endpoint.getOperations()).hasSize(1);
 | 
								assertThat(endpoint.getOperations()).hasSize(1);
 | 
				
			||||||
			WebOperation operation = endpoint.getOperations().iterator().next();
 | 
								WebOperation operation = endpoint.getOperations().iterator().next();
 | 
				
			||||||
			Object invoker = ReflectionTestUtils.getField(operation, "invoker");
 | 
								Object invoker = ReflectionTestUtils.getField(operation, "invoker");
 | 
				
			||||||
| 
						 | 
					@ -207,10 +208,10 @@ public class WebEndpointDiscovererTests {
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void getEndpointsWhenOperationReturnsResourceShouldProduceApplicationOctetStream() {
 | 
						public void getEndpointsWhenOperationReturnsResourceShouldProduceApplicationOctetStream() {
 | 
				
			||||||
		load(ResourceEndpointConfiguration.class, (discoverer) -> {
 | 
							load(ResourceEndpointConfiguration.class, (discoverer) -> {
 | 
				
			||||||
			Map<String, ExposableWebEndpoint> endpoints = mapEndpoints(
 | 
								Map<EndpointId, ExposableWebEndpoint> endpoints = mapEndpoints(
 | 
				
			||||||
					discoverer.getEndpoints());
 | 
										discoverer.getEndpoints());
 | 
				
			||||||
			assertThat(endpoints).containsOnlyKeys("resource");
 | 
								assertThat(endpoints).containsOnlyKeys(EndpointId.of("resource"));
 | 
				
			||||||
			ExposableWebEndpoint endpoint = endpoints.get("resource");
 | 
								ExposableWebEndpoint endpoint = endpoints.get(EndpointId.of("resource"));
 | 
				
			||||||
			assertThat(requestPredicates(endpoint)).has(requestPredicates(
 | 
								assertThat(requestPredicates(endpoint)).has(requestPredicates(
 | 
				
			||||||
					path("resource").httpMethod(WebEndpointHttpMethod.GET).consumes()
 | 
										path("resource").httpMethod(WebEndpointHttpMethod.GET).consumes()
 | 
				
			||||||
							.produces("application/octet-stream")));
 | 
												.produces("application/octet-stream")));
 | 
				
			||||||
| 
						 | 
					@ -220,10 +221,11 @@ public class WebEndpointDiscovererTests {
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void getEndpointsWhenHasCustomMediaTypeShouldProduceCustomMediaType() {
 | 
						public void getEndpointsWhenHasCustomMediaTypeShouldProduceCustomMediaType() {
 | 
				
			||||||
		load(CustomMediaTypesEndpointConfiguration.class, (discoverer) -> {
 | 
							load(CustomMediaTypesEndpointConfiguration.class, (discoverer) -> {
 | 
				
			||||||
			Map<String, ExposableWebEndpoint> endpoints = mapEndpoints(
 | 
								Map<EndpointId, ExposableWebEndpoint> endpoints = mapEndpoints(
 | 
				
			||||||
					discoverer.getEndpoints());
 | 
										discoverer.getEndpoints());
 | 
				
			||||||
			assertThat(endpoints).containsOnlyKeys("custommediatypes");
 | 
								assertThat(endpoints).containsOnlyKeys(EndpointId.of("custommediatypes"));
 | 
				
			||||||
			ExposableWebEndpoint endpoint = endpoints.get("custommediatypes");
 | 
								ExposableWebEndpoint endpoint = endpoints
 | 
				
			||||||
 | 
										.get(EndpointId.of("custommediatypes"));
 | 
				
			||||||
			assertThat(requestPredicates(endpoint)).has(requestPredicates(
 | 
								assertThat(requestPredicates(endpoint)).has(requestPredicates(
 | 
				
			||||||
					path("custommediatypes").httpMethod(WebEndpointHttpMethod.GET)
 | 
										path("custommediatypes").httpMethod(WebEndpointHttpMethod.GET)
 | 
				
			||||||
							.consumes().produces("text/plain"),
 | 
												.consumes().produces("text/plain"),
 | 
				
			||||||
| 
						 | 
					@ -238,10 +240,10 @@ public class WebEndpointDiscovererTests {
 | 
				
			||||||
	public void getEndpointsWhenHasCustomPathShouldReturnCustomPath() {
 | 
						public void getEndpointsWhenHasCustomPathShouldReturnCustomPath() {
 | 
				
			||||||
		load((id) -> null, (id) -> "custom/" + id,
 | 
							load((id) -> null, (id) -> "custom/" + id,
 | 
				
			||||||
				AdditionalOperationWebEndpointConfiguration.class, (discoverer) -> {
 | 
									AdditionalOperationWebEndpointConfiguration.class, (discoverer) -> {
 | 
				
			||||||
					Map<String, ExposableWebEndpoint> endpoints = mapEndpoints(
 | 
										Map<EndpointId, ExposableWebEndpoint> endpoints = mapEndpoints(
 | 
				
			||||||
							discoverer.getEndpoints());
 | 
												discoverer.getEndpoints());
 | 
				
			||||||
					assertThat(endpoints).containsOnlyKeys("test");
 | 
										assertThat(endpoints).containsOnlyKeys(EndpointId.of("test"));
 | 
				
			||||||
					ExposableWebEndpoint endpoint = endpoints.get("test");
 | 
										ExposableWebEndpoint endpoint = endpoints.get(EndpointId.of("test"));
 | 
				
			||||||
					Condition<List<? extends WebOperationRequestPredicate>> expected = requestPredicates(
 | 
										Condition<List<? extends WebOperationRequestPredicate>> expected = requestPredicates(
 | 
				
			||||||
							path("custom/test").httpMethod(WebEndpointHttpMethod.GET)
 | 
												path("custom/test").httpMethod(WebEndpointHttpMethod.GET)
 | 
				
			||||||
									.consumes().produces("application/json"),
 | 
														.consumes().produces("application/json"),
 | 
				
			||||||
| 
						 | 
					@ -255,8 +257,9 @@ public class WebEndpointDiscovererTests {
 | 
				
			||||||
		this.load((id) -> null, (id) -> id, configuration, consumer);
 | 
							this.load((id) -> null, (id) -> id, configuration, consumer);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private void load(Function<String, Long> timeToLive, PathMapper endpointPathMapper,
 | 
						private void load(Function<EndpointId, Long> timeToLive,
 | 
				
			||||||
			Class<?> configuration, Consumer<WebEndpointDiscoverer> consumer) {
 | 
								PathMapper endpointPathMapper, Class<?> configuration,
 | 
				
			||||||
 | 
								Consumer<WebEndpointDiscoverer> consumer) {
 | 
				
			||||||
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
 | 
							AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
 | 
				
			||||||
				configuration);
 | 
									configuration);
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
| 
						 | 
					@ -276,10 +279,11 @@ public class WebEndpointDiscovererTests {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private Map<String, ExposableWebEndpoint> mapEndpoints(
 | 
						private Map<EndpointId, ExposableWebEndpoint> mapEndpoints(
 | 
				
			||||||
			Collection<ExposableWebEndpoint> endpoints) {
 | 
								Collection<ExposableWebEndpoint> endpoints) {
 | 
				
			||||||
		Map<String, ExposableWebEndpoint> endpointById = new HashMap<>();
 | 
							Map<EndpointId, ExposableWebEndpoint> endpointById = new HashMap<>();
 | 
				
			||||||
		endpoints.forEach((endpoint) -> endpointById.put(endpoint.getId(), endpoint));
 | 
							endpoints.forEach(
 | 
				
			||||||
 | 
									(endpoint) -> endpointById.put(endpoint.getEndpointId(), endpoint));
 | 
				
			||||||
		return endpointById;
 | 
							return endpointById;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,7 @@ import org.junit.Rule;
 | 
				
			||||||
import org.junit.Test;
 | 
					import org.junit.Test;
 | 
				
			||||||
import org.junit.rules.ExpectedException;
 | 
					import org.junit.rules.ExpectedException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
 | 
					import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.web.annotation.ExposableControllerEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.web.annotation.ExposableControllerEndpoint;
 | 
				
			||||||
| 
						 | 
					@ -121,22 +122,22 @@ public class ControllerEndpointHandlerMappingTests {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private ExposableControllerEndpoint firstEndpoint() {
 | 
						private ExposableControllerEndpoint firstEndpoint() {
 | 
				
			||||||
		return mockEndpoint("first", new FirstTestMvcEndpoint());
 | 
							return mockEndpoint(EndpointId.of("first"), new FirstTestMvcEndpoint());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private ExposableControllerEndpoint secondEndpoint() {
 | 
						private ExposableControllerEndpoint secondEndpoint() {
 | 
				
			||||||
		return mockEndpoint("second", new SecondTestMvcEndpoint());
 | 
							return mockEndpoint(EndpointId.of("second"), new SecondTestMvcEndpoint());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private ExposableControllerEndpoint pathlessEndpoint() {
 | 
						private ExposableControllerEndpoint pathlessEndpoint() {
 | 
				
			||||||
		return mockEndpoint("pathless", new PathlessControllerEndpoint());
 | 
							return mockEndpoint(EndpointId.of("pathless"), new PathlessControllerEndpoint());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private ExposableControllerEndpoint mockEndpoint(String id, Object controller) {
 | 
						private ExposableControllerEndpoint mockEndpoint(EndpointId id, Object controller) {
 | 
				
			||||||
		ExposableControllerEndpoint endpoint = mock(ExposableControllerEndpoint.class);
 | 
							ExposableControllerEndpoint endpoint = mock(ExposableControllerEndpoint.class);
 | 
				
			||||||
		given(endpoint.getId()).willReturn(id);
 | 
							given(endpoint.getEndpointId()).willReturn(id);
 | 
				
			||||||
		given(endpoint.getController()).willReturn(controller);
 | 
							given(endpoint.getController()).willReturn(controller);
 | 
				
			||||||
		given(endpoint.getRootPath()).willReturn(id);
 | 
							given(endpoint.getRootPath()).willReturn(id.toString());
 | 
				
			||||||
		return endpoint;
 | 
							return endpoint;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,7 @@ import org.junit.Rule;
 | 
				
			||||||
import org.junit.Test;
 | 
					import org.junit.Test;
 | 
				
			||||||
import org.junit.rules.ExpectedException;
 | 
					import org.junit.rules.ExpectedException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.boot.actuate.endpoint.EndpointId;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
 | 
					import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpoint;
 | 
				
			||||||
import org.springframework.boot.actuate.endpoint.web.annotation.ExposableControllerEndpoint;
 | 
					import org.springframework.boot.actuate.endpoint.web.annotation.ExposableControllerEndpoint;
 | 
				
			||||||
| 
						 | 
					@ -113,22 +114,22 @@ public class ControllerEndpointHandlerMappingTests {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private ExposableControllerEndpoint firstEndpoint() {
 | 
						private ExposableControllerEndpoint firstEndpoint() {
 | 
				
			||||||
		return mockEndpoint("first", new FirstTestMvcEndpoint());
 | 
							return mockEndpoint(EndpointId.of("first"), new FirstTestMvcEndpoint());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private ExposableControllerEndpoint secondEndpoint() {
 | 
						private ExposableControllerEndpoint secondEndpoint() {
 | 
				
			||||||
		return mockEndpoint("second", new SecondTestMvcEndpoint());
 | 
							return mockEndpoint(EndpointId.of("second"), new SecondTestMvcEndpoint());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private ExposableControllerEndpoint pathlessEndpoint() {
 | 
						private ExposableControllerEndpoint pathlessEndpoint() {
 | 
				
			||||||
		return mockEndpoint("pathless", new PathlessControllerEndpoint());
 | 
							return mockEndpoint(EndpointId.of("pathless"), new PathlessControllerEndpoint());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private ExposableControllerEndpoint mockEndpoint(String id, Object controller) {
 | 
						private ExposableControllerEndpoint mockEndpoint(EndpointId id, Object controller) {
 | 
				
			||||||
		ExposableControllerEndpoint endpoint = mock(ExposableControllerEndpoint.class);
 | 
							ExposableControllerEndpoint endpoint = mock(ExposableControllerEndpoint.class);
 | 
				
			||||||
		given(endpoint.getId()).willReturn(id);
 | 
							given(endpoint.getEndpointId()).willReturn(id);
 | 
				
			||||||
		given(endpoint.getController()).willReturn(controller);
 | 
							given(endpoint.getController()).willReturn(controller);
 | 
				
			||||||
		given(endpoint.getRootPath()).willReturn(id);
 | 
							given(endpoint.getRootPath()).willReturn(id.toString());
 | 
				
			||||||
		return endpoint;
 | 
							return endpoint;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,7 +48,7 @@ public class MetricsWebFilterTests {
 | 
				
			||||||
		MockClock clock = new MockClock();
 | 
							MockClock clock = new MockClock();
 | 
				
			||||||
		this.registry = new SimpleMeterRegistry(SimpleConfig.DEFAULT, clock);
 | 
							this.registry = new SimpleMeterRegistry(SimpleConfig.DEFAULT, clock);
 | 
				
			||||||
		this.webFilter = new MetricsWebFilter(this.registry,
 | 
							this.webFilter = new MetricsWebFilter(this.registry,
 | 
				
			||||||
				new DefaultWebFluxTagsProvider(), REQUEST_METRICS_NAME);
 | 
									new DefaultWebFluxTagsProvider(), REQUEST_METRICS_NAME, true);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue