Merge branch '1.5.x'
This commit is contained in:
@@ -159,9 +159,11 @@ public class EndpointWebMvcManagementContextConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnBean(HealthEndpoint.class)
|
||||
@ConditionalOnEnabledEndpoint("health")
|
||||
public HealthMvcEndpoint healthMvcEndpoint(HealthEndpoint delegate) {
|
||||
public HealthMvcEndpoint healthMvcEndpoint(HealthEndpoint delegate,
|
||||
ManagementServerProperties managementServerProperties) {
|
||||
HealthMvcEndpoint healthMvcEndpoint = new HealthMvcEndpoint(delegate,
|
||||
this.managementServerProperties.getSecurity().isEnabled());
|
||||
this.managementServerProperties.getSecurity().isEnabled(),
|
||||
managementServerProperties.getSecurity().getRoles());
|
||||
if (this.healthMvcEndpointProperties.getMapping() != null) {
|
||||
healthMvcEndpoint
|
||||
.addStatusMapping(this.healthMvcEndpointProperties.getMapping());
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
package org.springframework.boot.actuate.endpoint.mvc;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -52,6 +54,8 @@ public class HealthMvcEndpoint extends AbstractEndpointMvcAdapter<HealthEndpoint
|
||||
|
||||
private final boolean secure;
|
||||
|
||||
private final List<String> roles;
|
||||
|
||||
private Map<String, HttpStatus> statusMapping = new HashMap<String, HttpStatus>();
|
||||
|
||||
private RelaxedPropertyResolver securityPropertyResolver;
|
||||
@@ -65,9 +69,15 @@ public class HealthMvcEndpoint extends AbstractEndpointMvcAdapter<HealthEndpoint
|
||||
}
|
||||
|
||||
public HealthMvcEndpoint(HealthEndpoint delegate, boolean secure) {
|
||||
this(delegate, secure, null);
|
||||
}
|
||||
|
||||
public HealthMvcEndpoint(HealthEndpoint delegate, boolean secure,
|
||||
List<String> roles) {
|
||||
super(delegate);
|
||||
this.secure = secure;
|
||||
setupDefaultStatusMapping();
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
private void setupDefaultStatusMapping() {
|
||||
@@ -173,10 +183,7 @@ public class HealthMvcEndpoint extends AbstractEndpointMvcAdapter<HealthEndpoint
|
||||
if (!this.secure) {
|
||||
return true;
|
||||
}
|
||||
String[] roles = StringUtils.commaDelimitedListToStringArray(
|
||||
this.securityPropertyResolver.getProperty("roles", "ROLE_ACTUATOR"));
|
||||
roles = StringUtils.trimArrayElements(roles);
|
||||
for (String role : roles) {
|
||||
for (String role : getRoles()) {
|
||||
if (request.isUserInRole(role) || request.isUserInRole("ROLE_" + role)) {
|
||||
return true;
|
||||
}
|
||||
@@ -184,4 +191,14 @@ public class HealthMvcEndpoint extends AbstractEndpointMvcAdapter<HealthEndpoint
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<String> getRoles() {
|
||||
if (this.roles != null) {
|
||||
return this.roles;
|
||||
}
|
||||
String[] roles = StringUtils.commaDelimitedListToStringArray(
|
||||
this.securityPropertyResolver.getProperty("roles", "ROLE_ACTUATOR"));
|
||||
roles = StringUtils.trimArrayElements(roles);
|
||||
return Arrays.asList(roles);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -125,10 +125,14 @@ public class MvcEndpointSecurityInterceptor extends HandlerInterceptorAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
private class AuthoritiesValidator {
|
||||
/**
|
||||
* Inner class to check authorities using Spring Security (when available).
|
||||
*/
|
||||
private static class AuthoritiesValidator {
|
||||
|
||||
private boolean hasAuthority(String role) {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
Authentication authentication = SecurityContextHolder.getContext()
|
||||
.getAuthentication();
|
||||
if (authentication != null) {
|
||||
for (GrantedAuthority authority : authentication.getAuthorities()) {
|
||||
if (authority.getAuthority().equals(role)) {
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -34,6 +36,7 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -83,6 +86,20 @@ public class HealthMvcEndpointAutoConfigurationTests {
|
||||
assertThat(map.getDetails().get("foo")).isEqualTo("bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetRoles() throws Exception {
|
||||
// gh-8314
|
||||
this.context = new AnnotationConfigWebApplicationContext();
|
||||
this.context.setServletContext(new MockServletContext());
|
||||
this.context.register(TestConfiguration.class);
|
||||
EnvironmentTestUtils.addEnvironment(this.context,
|
||||
"management.security.roles[0]=super");
|
||||
this.context.refresh();
|
||||
HealthMvcEndpoint health = this.context.getBean(HealthMvcEndpoint.class);
|
||||
assertThat(ReflectionTestUtils.getField(health, "roles"))
|
||||
.isEqualTo(Arrays.asList("super"));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ImportAutoConfiguration({ SecurityAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.boot.actuate.endpoint.mvc;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -182,6 +183,19 @@ public class HealthMvcEndpointTests {
|
||||
assertThat(((Health) result).getDetails().get("foo")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customRoleFromListShouldNotExposeDetailsForDefaultRole() {
|
||||
// gh-8314
|
||||
this.mvc = new HealthMvcEndpoint(this.endpoint, true,
|
||||
Arrays.asList("HERO", "USER"));
|
||||
given(this.endpoint.invoke())
|
||||
.willReturn(new Health.Builder().up().withDetail("foo", "bar").build());
|
||||
Object result = this.mvc.invoke(this.hero);
|
||||
assertThat(result instanceof Health).isTrue();
|
||||
assertThat(((Health) result).getStatus() == Status.UP).isTrue();
|
||||
assertThat(((Health) result).getDetails().get("foo")).isEqualTo("bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void healthIsCached() {
|
||||
given(this.endpoint.getTimeToLive()).willReturn(10000L);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
* Copyright 2012-2017 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.
|
||||
@@ -130,11 +130,13 @@ public class MvcEndpointSecurityInterceptorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sensitiveEndpointIfRoleNotCorrectShouldCheckAuthorities() throws Exception {
|
||||
public void sensitiveEndpointIfRoleNotCorrectShouldCheckAuthorities()
|
||||
throws Exception {
|
||||
Principal principal = mock(Principal.class);
|
||||
this.request.setUserPrincipal(principal);
|
||||
Authentication authentication = mock(Authentication.class);
|
||||
Set<SimpleGrantedAuthority> authorities = Collections.singleton(new SimpleGrantedAuthority("SUPER_HERO"));
|
||||
Set<SimpleGrantedAuthority> authorities = Collections
|
||||
.singleton(new SimpleGrantedAuthority("SUPER_HERO"));
|
||||
doReturn(authorities).when(authentication).getAuthorities();
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
assertThat(this.securityInterceptor.preHandle(this.request, this.response,
|
||||
@@ -142,11 +144,13 @@ public class MvcEndpointSecurityInterceptorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sensitiveEndpointIfRoleAndAuthoritiesNotCorrectShouldNotAllowAccess() throws Exception {
|
||||
public void sensitiveEndpointIfRoleAndAuthoritiesNotCorrectShouldNotAllowAccess()
|
||||
throws Exception {
|
||||
Principal principal = mock(Principal.class);
|
||||
this.request.setUserPrincipal(principal);
|
||||
Authentication authentication = mock(Authentication.class);
|
||||
Set<SimpleGrantedAuthority> authorities = Collections.singleton(new SimpleGrantedAuthority("HERO"));
|
||||
Set<SimpleGrantedAuthority> authorities = Collections
|
||||
.singleton(new SimpleGrantedAuthority("HERO"));
|
||||
doReturn(authorities).when(authentication).getAuthorities();
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
assertThat(this.securityInterceptor.preHandle(this.request, this.response,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -39,6 +39,8 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link MvcEndpointSecurityInterceptor} when Spring Security is not available.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
@RunWith(ModifiedClassPathRunner.class)
|
||||
@@ -77,7 +79,8 @@ public class NoSpringSecurityMvcEndpointSecurityInterceptorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sensitiveEndpointIfRoleNotPresentShouldNotValidateAuthorities() throws Exception {
|
||||
public void sensitiveEndpointIfRoleNotPresentShouldNotValidateAuthorities()
|
||||
throws Exception {
|
||||
Principal principal = mock(Principal.class);
|
||||
this.request.setUserPrincipal(principal);
|
||||
this.servletContext.declareRoles("HERO");
|
||||
@@ -105,5 +108,5 @@ public class NoSpringSecurityMvcEndpointSecurityInterceptorTests {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -64,20 +64,33 @@ class DataSourceInitializedPublisher implements BeanPostProcessor {
|
||||
if (bean instanceof JpaProperties) {
|
||||
this.properties = (JpaProperties) bean;
|
||||
}
|
||||
if (bean instanceof EntityManagerFactory && this.dataSource != null
|
||||
&& isInitializingDatabase()) {
|
||||
this.applicationContext
|
||||
.publishEvent(new DataSourceInitializedEvent(this.dataSource));
|
||||
if (bean instanceof EntityManagerFactory) {
|
||||
publishEventIfRequired((EntityManagerFactory) bean);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
private boolean isInitializingDatabase() {
|
||||
private void publishEventIfRequired(EntityManagerFactory entityManagerFactory) {
|
||||
DataSource dataSource = findDataSource(entityManagerFactory);
|
||||
if (dataSource != null && isInitializingDatabase(dataSource)) {
|
||||
this.applicationContext
|
||||
.publishEvent(new DataSourceInitializedEvent(dataSource));
|
||||
}
|
||||
}
|
||||
|
||||
private DataSource findDataSource(EntityManagerFactory entityManagerFactory) {
|
||||
Object dataSource = entityManagerFactory.getProperties()
|
||||
.get("javax.persistence.nonJtaDataSource");
|
||||
return (dataSource != null && dataSource instanceof DataSource
|
||||
? (DataSource) dataSource : this.dataSource);
|
||||
}
|
||||
|
||||
private boolean isInitializingDatabase(DataSource dataSource) {
|
||||
if (this.properties == null) {
|
||||
return true; // better safe than sorry
|
||||
}
|
||||
Map<String, String> hibernate = this.properties
|
||||
.getHibernateProperties(this.dataSource);
|
||||
.getHibernateProperties(dataSource);
|
||||
if (hibernate.containsKey("hibernate.hbm2ddl.auto")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
* Copyright 2012-2017 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.
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.springframework.boot.maven;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
@@ -87,29 +87,15 @@ public abstract class AbstractDependencyFilterMojo extends AbstractMojo {
|
||||
this.excludeArtifactIds = excludeArtifactIds;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Set<Artifact> filterDependencies(Set<Artifact> dependencies,
|
||||
FilterArtifacts filters) throws MojoExecutionException {
|
||||
List<ArtifactsFilter> artifactsFilters = filters.getFilters();
|
||||
try {
|
||||
for (ArtifactsFilter filter : artifactsFilters) {
|
||||
Set<Artifact> result = filter.filter(dependencies);
|
||||
applyFiltering(dependencies, result);
|
||||
}
|
||||
return dependencies;
|
||||
Set<Artifact> filtered = new LinkedHashSet<Artifact>(dependencies);
|
||||
filtered.retainAll(filters.filter(dependencies));
|
||||
return filtered;
|
||||
}
|
||||
catch (ArtifactFilterException e) {
|
||||
throw new MojoExecutionException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void applyFiltering(Set<Artifact> original, Set<Artifact> filtered) {
|
||||
Iterator<Artifact> iterator = original.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Artifact element = iterator.next();
|
||||
if (!filtered.contains(element)) {
|
||||
iterator.remove();
|
||||
}
|
||||
catch (ArtifactFilterException ex) {
|
||||
throw new MojoExecutionException(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ public class DependencyFilterMojoTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterExcludeKeepOrder() throws MojoExecutionException {
|
||||
public void filterExcludeKeepOrder() throws MojoExecutionException {
|
||||
Exclude exclude = new Exclude();
|
||||
exclude.setGroupId("com.bar");
|
||||
exclude.setArtifactId("two");
|
||||
@@ -121,7 +121,8 @@ public class DependencyFilterMojoTests {
|
||||
return createArtifact(groupId, artifactId, null);
|
||||
}
|
||||
|
||||
private static Artifact createArtifact(String groupId, String artifactId, String scope) {
|
||||
private static Artifact createArtifact(String groupId, String artifactId,
|
||||
String scope) {
|
||||
Artifact a = mock(Artifact.class);
|
||||
given(a.getGroupId()).willReturn(groupId);
|
||||
given(a.getArtifactId()).willReturn(artifactId);
|
||||
|
||||
@@ -205,9 +205,6 @@ public class JettyEmbeddedServletContainer implements EmbeddedWebServer {
|
||||
@Override
|
||||
public void stop() {
|
||||
synchronized (this.monitor) {
|
||||
if (!this.started) {
|
||||
return;
|
||||
}
|
||||
this.started = false;
|
||||
try {
|
||||
this.server.stop();
|
||||
|
||||
@@ -90,32 +90,38 @@ public class TomcatEmbeddedServletContainer implements EmbeddedWebServer {
|
||||
synchronized (this.monitor) {
|
||||
try {
|
||||
addInstanceIdToEngineName();
|
||||
|
||||
// Remove service connectors to that protocol binding doesn't happen yet
|
||||
removeServiceConnectors();
|
||||
|
||||
// Start the server to trigger initialization listeners
|
||||
this.tomcat.start();
|
||||
|
||||
// We can re-throw failure exception directly in the main thread
|
||||
rethrowDeferredStartupExceptions();
|
||||
|
||||
Context context = findContext();
|
||||
try {
|
||||
ContextBindings.bindClassLoader(context, context.getNamingToken(),
|
||||
getClass().getClassLoader());
|
||||
}
|
||||
catch (NamingException ex) {
|
||||
// Naming is not enabled. Continue
|
||||
}
|
||||
// Remove service connectors to that protocol binding doesn't happen
|
||||
// yet
|
||||
removeServiceConnectors();
|
||||
|
||||
// Unlike Jetty, all Tomcat threads are daemon threads. We create a
|
||||
// blocking non-daemon to stop immediate shutdown
|
||||
startDaemonAwaitThread();
|
||||
// Start the server to trigger initialization listeners
|
||||
this.tomcat.start();
|
||||
|
||||
// We can re-throw failure exception directly in the main thread
|
||||
rethrowDeferredStartupExceptions();
|
||||
|
||||
Context context = findContext();
|
||||
try {
|
||||
ContextBindings.bindClassLoader(context, context.getNamingToken(),
|
||||
getClass().getClassLoader());
|
||||
}
|
||||
catch (NamingException ex) {
|
||||
// Naming is not enabled. Continue
|
||||
}
|
||||
|
||||
// Unlike Jetty, all Tomcat threads are daemon threads. We create a
|
||||
// blocking non-daemon to stop immediate shutdown
|
||||
startDaemonAwaitThread();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
containerCounter.decrementAndGet();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new EmbeddedWebServerException(
|
||||
"Unable to start embedded Tomcat", ex);
|
||||
throw new EmbeddedWebServerException("Unable to start embedded Tomcat",
|
||||
ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -279,9 +285,7 @@ public class TomcatEmbeddedServletContainer implements EmbeddedWebServer {
|
||||
@Override
|
||||
public void stop() throws EmbeddedWebServerException {
|
||||
synchronized (this.monitor) {
|
||||
if (!this.started) {
|
||||
return;
|
||||
}
|
||||
boolean wasStarted = this.started;
|
||||
try {
|
||||
this.started = false;
|
||||
try {
|
||||
@@ -293,11 +297,13 @@ public class TomcatEmbeddedServletContainer implements EmbeddedWebServer {
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new EmbeddedWebServerException(
|
||||
"Unable to stop embedded Tomcat", ex);
|
||||
throw new EmbeddedWebServerException("Unable to stop embedded Tomcat",
|
||||
ex);
|
||||
}
|
||||
finally {
|
||||
containerCounter.decrementAndGet();
|
||||
if (wasStarted) {
|
||||
containerCounter.decrementAndGet();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,6 +174,16 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
||||
assertThat(this.output.toString()).containsOnlyOnce("started on port");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stopCalledTwice() throws Exception {
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
this.container = factory
|
||||
.getEmbeddedServletContainer(exampleServletRegistration());
|
||||
this.container.start();
|
||||
this.container.stop();
|
||||
this.container.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyServerWhenPortIsMinusOne() throws Exception {
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
@@ -315,16 +325,6 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
||||
getFactory().setContextPath("/");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doubleStop() throws Exception {
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
this.container = factory
|
||||
.getEmbeddedServletContainer(exampleServletRegistration());
|
||||
this.container.start();
|
||||
this.container.stop();
|
||||
this.container.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleConfigurations() throws Exception {
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
|
||||
@@ -143,6 +143,16 @@ public class JettyEmbeddedServletContainerFactoryTests
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stopCalledWithoutStart() throws Exception {
|
||||
JettyEmbeddedServletContainerFactory factory = getFactory();
|
||||
this.container = factory
|
||||
.getEmbeddedServletContainer(exampleServletRegistration());
|
||||
this.container.stop();
|
||||
Server server = ((JettyEmbeddedServletContainer) this.container).getServer();
|
||||
assertThat(server.isStopped()).isTrue();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addConnector(final int port,
|
||||
AbstractEmbeddedServletContainerFactory factory) {
|
||||
|
||||
@@ -352,6 +352,16 @@ public class TomcatEmbeddedServletContainerFactoryTests
|
||||
.doesNotContain("appears to have started a thread named [main]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stopCalledWithoutStart() throws Exception {
|
||||
TomcatEmbeddedServletContainerFactory factory = getFactory();
|
||||
this.container = factory
|
||||
.getEmbeddedServletContainer(exampleServletRegistration());
|
||||
this.container.stop();
|
||||
Tomcat tomcat = ((TomcatEmbeddedServletContainer) this.container).getTomcat();
|
||||
assertThat(tomcat.getServer().getState()).isSameAs(LifecycleState.DESTROYED);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addConnector(int port,
|
||||
AbstractEmbeddedServletContainerFactory factory) {
|
||||
|
||||
Reference in New Issue
Block a user