Commit a323a85e authored by Phillip Webb's avatar Phillip Webb

Merge branch '2.0.x'

parents cdb5d76c 975e986f
...@@ -113,19 +113,56 @@ public final class EndpointRequest { ...@@ -113,19 +113,56 @@ public final class EndpointRequest {
} }
/** /**
* The request matcher used to match against {@link Endpoint actuator endpoints}. * Base class for supported request matchers.
*/ */
public static final class EndpointRequestMatcher private static abstract class AbstractRequestMatcher
extends ApplicationContextRequestMatcher<WebApplicationContext> { extends ApplicationContextRequestMatcher<WebApplicationContext> {
private volatile RequestMatcher delegate;
public AbstractRequestMatcher() {
super(WebApplicationContext.class);
}
@Override
protected final void initialized(Supplier<WebApplicationContext> context) {
this.delegate = createDelegate(context.get());
}
@Override
protected final boolean matches(HttpServletRequest request,
Supplier<WebApplicationContext> context) {
return this.delegate.matches(request);
}
private RequestMatcher createDelegate(WebApplicationContext context) {
try {
RequestMatcherFactory requestMatcherFactory = new RequestMatcherFactory(
context.getBean(DispatcherServletPathProvider.class)
.getServletPath());
return createDelegate(context, requestMatcherFactory);
}
catch (NoSuchBeanDefinitionException ex) {
return EMPTY_MATCHER;
}
}
protected abstract RequestMatcher createDelegate(WebApplicationContext context,
RequestMatcherFactory requestMatcherFactory);
}
/**
* The request matcher used to match against {@link Endpoint actuator endpoints}.
*/
public static final class EndpointRequestMatcher extends AbstractRequestMatcher {
private final List<Object> includes; private final List<Object> includes;
private final List<Object> excludes; private final List<Object> excludes;
private final boolean includeLinks; private final boolean includeLinks;
private volatile RequestMatcher delegate;
private EndpointRequestMatcher(boolean includeLinks) { private EndpointRequestMatcher(boolean includeLinks) {
this(Collections.emptyList(), Collections.emptyList(), includeLinks); this(Collections.emptyList(), Collections.emptyList(), includeLinks);
} }
...@@ -142,7 +179,6 @@ public final class EndpointRequest { ...@@ -142,7 +179,6 @@ public final class EndpointRequest {
private EndpointRequestMatcher(List<Object> includes, List<Object> excludes, private EndpointRequestMatcher(List<Object> includes, List<Object> excludes,
boolean includeLinks) { boolean includeLinks) {
super(WebApplicationContext.class);
this.includes = includes; this.includes = includes;
this.excludes = excludes; this.excludes = excludes;
this.includeLinks = includeLinks; this.includeLinks = includeLinks;
...@@ -165,40 +201,22 @@ public final class EndpointRequest { ...@@ -165,40 +201,22 @@ public final class EndpointRequest {
} }
@Override @Override
protected void initialized( protected RequestMatcher createDelegate(WebApplicationContext context,
Supplier<WebApplicationContext> webApplicationContext) { RequestMatcherFactory requestMatcherFactory) {
this.delegate = createDelegate(webApplicationContext); PathMappedEndpoints pathMappedEndpoints = context
} .getBean(PathMappedEndpoints.class);
private RequestMatcher createDelegate(
Supplier<WebApplicationContext> webApplicationContext) {
try {
WebApplicationContext context = webApplicationContext.get();
PathMappedEndpoints pathMappedEndpoints = context
.getBean(PathMappedEndpoints.class);
DispatcherServletPathProvider pathProvider = context
.getBean(DispatcherServletPathProvider.class);
return createDelegate(pathMappedEndpoints, pathProvider.getServletPath());
}
catch (NoSuchBeanDefinitionException ex) {
return EMPTY_MATCHER;
}
}
private RequestMatcher createDelegate(PathMappedEndpoints pathMappedEndpoints,
String servletPath) {
Set<String> paths = new LinkedHashSet<>(); Set<String> paths = new LinkedHashSet<>();
if (this.includes.isEmpty()) { if (this.includes.isEmpty()) {
paths.addAll(pathMappedEndpoints.getAllPaths()); paths.addAll(pathMappedEndpoints.getAllPaths());
} }
streamPaths(this.includes, pathMappedEndpoints).forEach(paths::add); streamPaths(this.includes, pathMappedEndpoints).forEach(paths::add);
streamPaths(this.excludes, pathMappedEndpoints).forEach(paths::remove); streamPaths(this.excludes, pathMappedEndpoints).forEach(paths::remove);
List<RequestMatcher> delegateMatchers = getDelegateMatchers(servletPath, List<RequestMatcher> delegateMatchers = getDelegateMatchers(
paths); requestMatcherFactory, paths);
if (this.includeLinks if (this.includeLinks
&& StringUtils.hasText(pathMappedEndpoints.getBasePath())) { && StringUtils.hasText(pathMappedEndpoints.getBasePath())) {
delegateMatchers.add(new AntPathRequestMatcher( delegateMatchers.add(
computePath(servletPath, pathMappedEndpoints.getBasePath()))); requestMatcherFactory.antPath(pathMappedEndpoints.getBasePath()));
} }
return new OrRequestMatcher(delegateMatchers); return new OrRequestMatcher(delegateMatchers);
} }
...@@ -226,75 +244,50 @@ public final class EndpointRequest { ...@@ -226,75 +244,50 @@ public final class EndpointRequest {
return annotation.id(); return annotation.id();
} }
private List<RequestMatcher> getDelegateMatchers(String servletPath, private List<RequestMatcher> getDelegateMatchers(
Set<String> paths) { RequestMatcherFactory requestMatcherFactory, Set<String> paths) {
return paths.stream() return paths.stream()
.map((path) -> new AntPathRequestMatcher(computePath(servletPath, path) + "/**")) .map((path) -> requestMatcherFactory.antPath(path, "/**"))
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
private String computePath(String servletPath, String path) {
if (servletPath.equals("/")) {
return path;
}
return servletPath + path;
}
@Override
protected boolean matches(HttpServletRequest request,
Supplier<WebApplicationContext> context) {
return this.delegate.matches(request);
}
} }
/** /**
* The request matcher used to match against the links endpoint. * The request matcher used to match against the links endpoint.
*/ */
public static final class LinksRequestMatcher public static final class LinksRequestMatcher extends AbstractRequestMatcher {
extends ApplicationContextRequestMatcher<WebApplicationContext> {
private RequestMatcher delegate;
private LinksRequestMatcher() {
super(WebApplicationContext.class);
}
@Override @Override
protected void initialized( protected RequestMatcher createDelegate(WebApplicationContext context,
Supplier<WebApplicationContext> webApplicationContext) { RequestMatcherFactory requestMatcherFactory) {
try { WebEndpointProperties properties = context
WebApplicationContext context = webApplicationContext.get(); .getBean(WebEndpointProperties.class);
WebEndpointProperties properties = context
.getBean(WebEndpointProperties.class);
DispatcherServletPathProvider pathProvider = context
.getBean(DispatcherServletPathProvider.class);
this.delegate = createDelegate(pathProvider.getServletPath(), properties);
}
catch (NoSuchBeanDefinitionException ex) {
this.delegate = EMPTY_MATCHER;
}
}
private RequestMatcher createDelegate(String path,
WebEndpointProperties properties) {
if (StringUtils.hasText(properties.getBasePath())) { if (StringUtils.hasText(properties.getBasePath())) {
return new AntPathRequestMatcher(computePath(path, properties.getBasePath())); return requestMatcherFactory.antPath(properties.getBasePath());
} }
return EMPTY_MATCHER; return EMPTY_MATCHER;
} }
private String computePath(String servletPath, String path) { }
if (servletPath.equals("/")) {
return path; /**
} * Factory used to create a {@link RequestMatcher}.
return servletPath + path; */
private static class RequestMatcherFactory {
private final String servletPath;
RequestMatcherFactory(String servletPath) {
this.servletPath = servletPath;
} }
@Override public RequestMatcher antPath(String... parts) {
protected boolean matches(HttpServletRequest request, String pattern = (this.servletPath.equals("/") ? "" : this.servletPath);
Supplier<WebApplicationContext> context) { for (String part : parts) {
return this.delegate.matches(request); pattern += part;
}
return new AntPathRequestMatcher(pattern);
} }
} }
......
...@@ -99,8 +99,9 @@ public class EndpointMBean implements DynamicMBean { ...@@ -99,8 +99,9 @@ public class EndpointMBean implements DynamicMBean {
String[] parameterNames = operation.getParameters().stream() String[] parameterNames = operation.getParameters().stream()
.map(JmxOperationParameter::getName).toArray(String[]::new); .map(JmxOperationParameter::getName).toArray(String[]::new);
Map<String, Object> arguments = getArguments(parameterNames, params); Map<String, Object> arguments = getArguments(parameterNames, params);
Object result = operation InvocationContext context = new InvocationContext(SecurityContext.NONE,
.invoke(new InvocationContext(SecurityContext.NONE, arguments)); arguments);
Object result = operation.invoke(context);
if (REACTOR_PRESENT) { if (REACTOR_PRESENT) {
result = ReactiveHandler.handle(result); result = ReactiveHandler.handle(result);
} }
...@@ -119,9 +120,7 @@ public class EndpointMBean implements DynamicMBean { ...@@ -119,9 +120,7 @@ public class EndpointMBean implements DynamicMBean {
if (exception.getClass().getName().startsWith("java.")) { if (exception.getClass().getName().startsWith("java.")) {
return exception; return exception;
} }
else { return new IllegalStateException(exception.getMessage());
return new IllegalStateException(exception.getMessage());
}
} }
private Map<String, Object> getArguments(String[] parameterNames, Object[] params) { private Map<String, Object> getArguments(String[] parameterNames, Object[] params) {
......
...@@ -130,10 +130,12 @@ public class EndpointMBeanTests { ...@@ -130,10 +130,12 @@ public class EndpointMBeanTests {
public void invokeWhenOperationIsInvalidShouldThrowException() public void invokeWhenOperationIsInvalidShouldThrowException()
throws MBeanException, ReflectionException { throws MBeanException, ReflectionException {
TestJmxOperation operation = new TestJmxOperation() { TestJmxOperation operation = new TestJmxOperation() {
@Override @Override
public Object invoke(InvocationContext context) { public Object invoke(InvocationContext context) {
throw new InvalidEndpointRequestException("test failure", "test"); throw new InvalidEndpointRequestException("test failure", "test");
} }
}; };
TestExposableJmxEndpoint endpoint = new TestExposableJmxEndpoint(operation); TestExposableJmxEndpoint endpoint = new TestExposableJmxEndpoint(operation);
EndpointMBean bean = new EndpointMBean(this.responseMapper, endpoint); EndpointMBean bean = new EndpointMBean(this.responseMapper, endpoint);
......
...@@ -831,7 +831,6 @@ public class WebMvcAutoConfigurationTests { ...@@ -831,7 +831,6 @@ public class WebMvcAutoConfigurationTests {
ContentNegotiationStrategy delegate = mock(ContentNegotiationStrategy.class); ContentNegotiationStrategy delegate = mock(ContentNegotiationStrategy.class);
ContentNegotiationStrategy strategy = new WebMvcAutoConfiguration.OptionalPathExtensionContentNegotiationStrategy( ContentNegotiationStrategy strategy = new WebMvcAutoConfiguration.OptionalPathExtensionContentNegotiationStrategy(
delegate); delegate);
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
request.setAttribute( request.setAttribute(
PathExtensionContentNegotiationStrategy.class.getName() + ".SKIP", PathExtensionContentNegotiationStrategy.class.getName() + ".SKIP",
......
...@@ -2600,7 +2600,7 @@ the artifact yourself instead of overriding the property. ...@@ -2600,7 +2600,7 @@ the artifact yourself instead of overriding the property.
WARNING: Each Spring Boot release is designed and tested against this specific set of WARNING: Each Spring Boot release is designed and tested against this specific set of
third-party dependencies. Overriding versions may cause compatibility issues. third-party dependencies. Overriding versions may cause compatibility issues.
To override dependency versions in Gradle, see {spring-boot-gradle-plugin-reference}/#managing-dependencies-customizing[ this section ] To override dependency versions in Gradle, see {spring-boot-gradle-plugin-reference}/#managing-dependencies-customizing[this section]
of the Gradle plugin's documentation. of the Gradle plugin's documentation.
[[howto-create-an-executable-jar-with-maven]] [[howto-create-an-executable-jar-with-maven]]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment