Browse Source
Provide application auto-configuration to provide remote endpoint support along with a client-side application that can be used to establish connections. See gh-3086pull/3077/merge
13 changed files with 674 additions and 1 deletions
@ -0,0 +1,76 @@
@@ -0,0 +1,76 @@
|
||||
/* |
||||
* Copyright 2012-2015 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.developertools; |
||||
|
||||
import org.springframework.boot.Banner; |
||||
import org.springframework.boot.ResourceBanner; |
||||
import org.springframework.boot.SpringApplication; |
||||
import org.springframework.boot.developertools.remote.client.RemoteClientConfiguration; |
||||
import org.springframework.boot.developertools.restart.RestartInitializer; |
||||
import org.springframework.boot.developertools.restart.Restarter; |
||||
import org.springframework.core.io.ClassPathResource; |
||||
|
||||
/** |
||||
* Application that can be used to establish a link to remotely running Spring Boot code. |
||||
* Allows remote debugging and remote updates (if enabled). This class should be launched |
||||
* from within your IDE and should have the same classpath configuration as the locally |
||||
* developed application. The remote URL of the application should be provided as a |
||||
* non-option argument. |
||||
* |
||||
* @author Phillip Webb |
||||
* @since 1.3.0 |
||||
* @see RemoteClientConfiguration |
||||
*/ |
||||
public class RemoteSpringApplication { |
||||
|
||||
private void run(String[] args) { |
||||
Restarter.initialize(args, RestartInitializer.NONE); |
||||
SpringApplication application = new SpringApplication( |
||||
RemoteClientConfiguration.class); |
||||
application.setWebEnvironment(false); |
||||
application.setBanner(getBanner()); |
||||
application.addListeners(new RemoteUrlPropertyExtractor()); |
||||
application.run(args); |
||||
waitIndefinitely(); |
||||
} |
||||
|
||||
private Banner getBanner() { |
||||
ClassPathResource banner = new ClassPathResource("remote-banner.txt", |
||||
RemoteSpringApplication.class); |
||||
return new ResourceBanner(banner); |
||||
} |
||||
|
||||
private void waitIndefinitely() { |
||||
while (true) { |
||||
try { |
||||
Thread.sleep(1000); |
||||
} |
||||
catch (InterruptedException ex) { |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Run the {@link RemoteSpringApplication}. |
||||
* @param args the program arguments (including the remote URL as a non-option |
||||
* argument) |
||||
*/ |
||||
public static void main(String[] args) { |
||||
new RemoteSpringApplication().run(args); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,61 @@
@@ -0,0 +1,61 @@
|
||||
/* |
||||
* Copyright 2012-2015 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.developertools; |
||||
|
||||
import java.net.URI; |
||||
import java.net.URISyntaxException; |
||||
import java.util.Collections; |
||||
import java.util.Map; |
||||
|
||||
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; |
||||
import org.springframework.context.ApplicationListener; |
||||
import org.springframework.core.env.CommandLinePropertySource; |
||||
import org.springframework.core.env.ConfigurableEnvironment; |
||||
import org.springframework.core.env.MapPropertySource; |
||||
import org.springframework.core.env.PropertySource; |
||||
import org.springframework.util.Assert; |
||||
import org.springframework.util.StringUtils; |
||||
|
||||
/** |
||||
* {@link ApplicationListener} to extract the remote URL for the |
||||
* {@link RemoteSpringApplication} to use. |
||||
* |
||||
* @author Phillip Webb |
||||
*/ |
||||
class RemoteUrlPropertyExtractor implements |
||||
ApplicationListener<ApplicationEnvironmentPreparedEvent> { |
||||
|
||||
private static final String NON_OPTION_ARGS = CommandLinePropertySource.DEFAULT_NON_OPTION_ARGS_PROPERTY_NAME; |
||||
|
||||
@Override |
||||
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) { |
||||
ConfigurableEnvironment environment = event.getEnvironment(); |
||||
String url = environment.getProperty(NON_OPTION_ARGS); |
||||
Assert.state(StringUtils.hasLength(url), "No remote URL specified"); |
||||
Assert.state(url.indexOf(",") == -1, "Multiple URLs specified"); |
||||
try { |
||||
new URI(url); |
||||
} |
||||
catch (URISyntaxException ex) { |
||||
throw new IllegalStateException("Malformed URL '" + url + "'"); |
||||
} |
||||
Map<String, Object> source = Collections.singletonMap("remoteUrl", (Object) url); |
||||
PropertySource<?> propertySource = new MapPropertySource("remoteUrl", source); |
||||
environment.getPropertySources().addLast(propertySource); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,70 @@
@@ -0,0 +1,70 @@
|
||||
/* |
||||
* Copyright 2012-2015 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.developertools.autoconfigure; |
||||
|
||||
import java.util.Collection; |
||||
|
||||
import javax.servlet.Filter; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties; |
||||
import org.springframework.boot.developertools.remote.server.AccessManager; |
||||
import org.springframework.boot.developertools.remote.server.Dispatcher; |
||||
import org.springframework.boot.developertools.remote.server.DispatcherFilter; |
||||
import org.springframework.boot.developertools.remote.server.Handler; |
||||
import org.springframework.boot.developertools.remote.server.HandlerMapper; |
||||
import org.springframework.boot.developertools.remote.server.HttpStatusHandler; |
||||
import org.springframework.boot.developertools.remote.server.UrlHandlerMapper; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.http.server.ServerHttpRequest; |
||||
|
||||
/** |
||||
* {@link EnableAutoConfiguration Auto-configuration} for remote development support. |
||||
* |
||||
* @author Phillip Webb |
||||
* @author Rob Winch |
||||
* @since 1.3.0 |
||||
*/ |
||||
@Configuration |
||||
@ConditionalOnProperty(prefix = "spring.developertools.remote", name = "enabled") |
||||
@ConditionalOnClass({ Filter.class, ServerHttpRequest.class }) |
||||
@EnableConfigurationProperties(DeveloperToolsProperties.class) |
||||
public class RemoteDeveloperToolsAutoConfiguration { |
||||
|
||||
@Autowired |
||||
private DeveloperToolsProperties properties; |
||||
|
||||
@Bean |
||||
public HandlerMapper remoteDeveloperToolsHealthCheckHandlerMapper() { |
||||
Handler handler = new HttpStatusHandler(); |
||||
return new UrlHandlerMapper(this.properties.getRemote().getContextPath(), handler); |
||||
} |
||||
|
||||
@Bean |
||||
@ConditionalOnMissingBean |
||||
public DispatcherFilter remoteDeveloperToolsDispatcherFilter( |
||||
Collection<HandlerMapper> mappers) { |
||||
Dispatcher dispatcher = new Dispatcher(AccessManager.PERMIT_ALL, mappers); |
||||
return new DispatcherFilter(dispatcher); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
/* |
||||
* Copyright 2012-2015 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.developertools.autoconfigure; |
||||
|
||||
|
||||
/** |
||||
* Configuration properties for remote Spring Boot applications. |
||||
* |
||||
* @author Phillip Webb |
||||
* @author Rob Winch |
||||
* @since 1.3.0 |
||||
* @see DeveloperToolsProperties |
||||
*/ |
||||
public class RemoteDeveloperToolsProperties { |
||||
|
||||
public static final String DEFAULT_CONTEXT_PATH = "/.~~spring-boot!~"; |
||||
|
||||
/** |
||||
* Context path used to handle the remote connection. |
||||
*/ |
||||
private String contextPath = DEFAULT_CONTEXT_PATH; |
||||
|
||||
public String getContextPath() { |
||||
return this.contextPath; |
||||
} |
||||
|
||||
public void setContextPath(String contextPath) { |
||||
this.contextPath = contextPath; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
/* |
||||
* Copyright 2012-2015 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. |
||||
*/ |
||||
|
||||
/** |
||||
* Spring Boot developer tools. |
||||
*/ |
||||
package org.springframework.boot.developertools; |
||||
|
||||
@ -0,0 +1,56 @@
@@ -0,0 +1,56 @@
|
||||
/* |
||||
* Copyright 2012-2015 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.developertools.remote.client; |
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.beans.factory.annotation.Value; |
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties; |
||||
import org.springframework.boot.developertools.autoconfigure.DeveloperToolsProperties; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; |
||||
import org.springframework.http.client.ClientHttpRequestFactory; |
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory; |
||||
|
||||
/** |
||||
* Configuration used to connect to remote Spring Boot applications. |
||||
* |
||||
* @author Phillip Webb |
||||
* @since 1.3.0 |
||||
* @see org.springframework.boot.developertools.RemoteSpringApplication |
||||
*/ |
||||
@Configuration |
||||
@EnableConfigurationProperties(DeveloperToolsProperties.class) |
||||
public class RemoteClientConfiguration { |
||||
|
||||
@Autowired |
||||
private DeveloperToolsProperties properties; |
||||
|
||||
@Value("${remoteUrl}") |
||||
private String remoteUrl; |
||||
|
||||
@Bean |
||||
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { |
||||
return new PropertySourcesPlaceholderConfigurer(); |
||||
} |
||||
|
||||
@Bean |
||||
public ClientHttpRequestFactory clientHttpRequestFactory() { |
||||
return new SimpleClientHttpRequestFactory(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
/* |
||||
* Copyright 2012-2015 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. |
||||
*/ |
||||
|
||||
/** |
||||
* Client support for a remotely running Spring Boot application. |
||||
*/ |
||||
package org.springframework.boot.developertools.remote.client; |
||||
|
||||
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
. ____ _ __ _ _ |
||||
/\\ / ___'_ __ _ _(_)_ __ __ _ ___ _ \ \ \ \ |
||||
( ( )\___ | '_ | '_| | '_ \/ _` | | _ \___ _ __ ___| |_ ___ \ \ \ \ |
||||
\\/ ___)| |_)| | | | | || (_| []::::::[] / -_) ' \/ _ \ _/ -_) ) ) ) ) |
||||
' |____| .__|_| |_|_| |_\__, | |_|_\___|_|_|_\___/\__\___|/ / / / |
||||
=========|_|==============|___/===================================/_/_/_/ |
||||
:: Spring Boot Remote :: ${spring-boot.formatted-version} |
||||
@ -0,0 +1,81 @@
@@ -0,0 +1,81 @@
|
||||
/* |
||||
* Copyright 2012-2015 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.developertools; |
||||
|
||||
import org.junit.Rule; |
||||
import org.junit.Test; |
||||
import org.junit.rules.ExpectedException; |
||||
import org.springframework.boot.SpringApplication; |
||||
import org.springframework.boot.developertools.RemoteUrlPropertyExtractor; |
||||
import org.springframework.context.ApplicationContext; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
import static org.hamcrest.Matchers.equalTo; |
||||
import static org.junit.Assert.assertThat; |
||||
|
||||
/** |
||||
* Tests for {@link RemoteUrlPropertyExtractor}. |
||||
* |
||||
* @author Phillip Webb |
||||
*/ |
||||
public class RemoteUrlPropertyExtractorTests { |
||||
|
||||
@Rule |
||||
public ExpectedException thrown = ExpectedException.none(); |
||||
|
||||
@Test |
||||
public void missingUrl() throws Exception { |
||||
this.thrown.expect(IllegalStateException.class); |
||||
this.thrown.expectMessage("No remote URL specified"); |
||||
doTest(); |
||||
} |
||||
|
||||
@Test |
||||
public void malformedUrl() throws Exception { |
||||
this.thrown.expect(IllegalStateException.class); |
||||
this.thrown.expectMessage("Malformed URL '::://wibble'"); |
||||
doTest("::://wibble"); |
||||
|
||||
} |
||||
|
||||
@Test |
||||
public void multipleUrls() throws Exception { |
||||
this.thrown.expect(IllegalStateException.class); |
||||
this.thrown.expectMessage("Multiple URLs specified"); |
||||
doTest("http://localhost:8080", "http://localhost:9090"); |
||||
} |
||||
|
||||
@Test |
||||
public void validUrl() throws Exception { |
||||
ApplicationContext context = doTest("http://localhost:8080"); |
||||
assertThat(context.getEnvironment().getProperty("remoteUrl"), |
||||
equalTo("http://localhost:8080")); |
||||
} |
||||
|
||||
private ApplicationContext doTest(String... args) { |
||||
SpringApplication application = new SpringApplication(Config.class); |
||||
application.setWebEnvironment(false); |
||||
application.addListeners(new RemoteUrlPropertyExtractor()); |
||||
return application.run(args); |
||||
} |
||||
|
||||
@Configuration |
||||
static class Config { |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,102 @@
@@ -0,0 +1,102 @@
|
||||
/* |
||||
* Copyright 2012-2015 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.developertools.autoconfigure; |
||||
|
||||
import org.junit.After; |
||||
import org.junit.Before; |
||||
import org.junit.Rule; |
||||
import org.junit.Test; |
||||
import org.junit.rules.ExpectedException; |
||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; |
||||
import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration; |
||||
import org.springframework.boot.developertools.remote.server.DispatcherFilter; |
||||
import org.springframework.boot.developertools.restart.MockRestarter; |
||||
import org.springframework.boot.test.EnvironmentTestUtils; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.context.annotation.Import; |
||||
import org.springframework.mock.web.MockFilterChain; |
||||
import org.springframework.mock.web.MockHttpServletRequest; |
||||
import org.springframework.mock.web.MockHttpServletResponse; |
||||
import org.springframework.mock.web.MockServletContext; |
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; |
||||
|
||||
import static org.hamcrest.Matchers.equalTo; |
||||
import static org.junit.Assert.assertThat; |
||||
|
||||
/** |
||||
* Tests for {@link RemoteDeveloperToolsAutoConfiguration}. |
||||
* |
||||
* @author Rob Winch |
||||
* @author Phillip Webb |
||||
*/ |
||||
public class RemoteDeveloperToolsAutoConfigurationTests { |
||||
|
||||
private static final String DEFAULT_CONTEXT_PATH = RemoteDeveloperToolsProperties.DEFAULT_CONTEXT_PATH; |
||||
|
||||
@Rule |
||||
public MockRestarter mockRestarter = new MockRestarter(); |
||||
|
||||
@Rule |
||||
public ExpectedException thrown = ExpectedException.none(); |
||||
|
||||
private AnnotationConfigWebApplicationContext context; |
||||
|
||||
private MockHttpServletRequest request; |
||||
|
||||
private MockHttpServletResponse response; |
||||
|
||||
private MockFilterChain chain; |
||||
|
||||
@Before |
||||
public void setup() { |
||||
this.request = new MockHttpServletRequest(); |
||||
this.response = new MockHttpServletResponse(); |
||||
this.chain = new MockFilterChain(); |
||||
} |
||||
|
||||
@After |
||||
public void close() { |
||||
if (this.context != null) { |
||||
this.context.close(); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void developerToolsHealthReturns200() throws Exception { |
||||
loadContext("spring.developertools.remote.enabled:true"); |
||||
DispatcherFilter filter = this.context.getBean(DispatcherFilter.class); |
||||
this.request.setRequestURI(DEFAULT_CONTEXT_PATH); |
||||
this.response.setStatus(500); |
||||
filter.doFilter(this.request, this.response, this.chain); |
||||
assertThat(this.response.getStatus(), equalTo(200)); |
||||
} |
||||
|
||||
private void loadContext(String... properties) { |
||||
this.context = new AnnotationConfigWebApplicationContext(); |
||||
this.context.setServletContext(new MockServletContext()); |
||||
this.context.register(Config.class, ServerPropertiesAutoConfiguration.class, |
||||
PropertyPlaceholderAutoConfiguration.class); |
||||
EnvironmentTestUtils.addEnvironment(this.context, properties); |
||||
this.context.refresh(); |
||||
} |
||||
|
||||
@Configuration |
||||
@Import(RemoteDeveloperToolsAutoConfiguration.class) |
||||
static class Config { |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,126 @@
@@ -0,0 +1,126 @@
|
||||
/* |
||||
* Copyright 2012-2015 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.developertools.remote.client; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import org.junit.After; |
||||
import org.junit.Rule; |
||||
import org.junit.Test; |
||||
import org.junit.rules.ExpectedException; |
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException; |
||||
import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext; |
||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; |
||||
import org.springframework.boot.developertools.classpath.ClassPathFileSystemWatcher; |
||||
import org.springframework.boot.developertools.remote.server.Dispatcher; |
||||
import org.springframework.boot.developertools.remote.server.DispatcherFilter; |
||||
import org.springframework.boot.developertools.restart.MockRestarter; |
||||
import org.springframework.boot.developertools.restart.RestartScopeInitializer; |
||||
import org.springframework.boot.test.EnvironmentTestUtils; |
||||
import org.springframework.boot.test.OutputCapture; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.http.server.ServerHttpRequest; |
||||
import org.springframework.http.server.ServerHttpResponse; |
||||
import org.springframework.util.SocketUtils; |
||||
|
||||
import static org.hamcrest.Matchers.containsString; |
||||
import static org.hamcrest.Matchers.not; |
||||
import static org.junit.Assert.assertThat; |
||||
import static org.mockito.BDDMockito.given; |
||||
import static org.mockito.Matchers.any; |
||||
import static org.mockito.Mockito.mock; |
||||
|
||||
/** |
||||
* Tests for {@link RemoteClientConfiguration}. |
||||
* |
||||
* @author Phillip Webb |
||||
*/ |
||||
public class RemoteClientConfigurationTests { |
||||
|
||||
@Rule |
||||
public MockRestarter restarter = new MockRestarter(); |
||||
|
||||
@Rule |
||||
public OutputCapture output = new OutputCapture(); |
||||
|
||||
@Rule |
||||
public ExpectedException thrown = ExpectedException.none(); |
||||
|
||||
private AnnotationConfigEmbeddedWebApplicationContext context; |
||||
|
||||
private static int remotePort = SocketUtils.findAvailableTcpPort(); |
||||
|
||||
@After |
||||
public void cleanup() { |
||||
if (this.context != null) { |
||||
this.context.close(); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void doesntWarnIfUsingHttps() throws Exception { |
||||
configureWithRemoteUrl("https://localhost"); |
||||
assertThat(this.output.toString(), not(containsString("is insecure"))); |
||||
} |
||||
|
||||
@Test |
||||
public void remoteRestartDisabled() throws Exception { |
||||
configure("spring.developertools.remote.restart.enabled:false"); |
||||
this.thrown.expect(NoSuchBeanDefinitionException.class); |
||||
this.context.getBean(ClassPathFileSystemWatcher.class); |
||||
} |
||||
|
||||
private void configure(String... pairs) { |
||||
configureWithRemoteUrl("http://localhost", pairs); |
||||
} |
||||
|
||||
private void configureWithRemoteUrl(String remoteUrl, String... pairs) { |
||||
this.context = new AnnotationConfigEmbeddedWebApplicationContext(); |
||||
new RestartScopeInitializer().initialize(this.context); |
||||
this.context.register(Config.class, RemoteClientConfiguration.class); |
||||
String remoteUrlProperty = "remoteUrl:" + remoteUrl + ":" |
||||
+ RemoteClientConfigurationTests.remotePort; |
||||
EnvironmentTestUtils.addEnvironment(this.context, remoteUrlProperty); |
||||
EnvironmentTestUtils.addEnvironment(this.context, pairs); |
||||
this.context.refresh(); |
||||
} |
||||
|
||||
@Configuration |
||||
static class Config { |
||||
|
||||
@Bean |
||||
public TomcatEmbeddedServletContainerFactory tomcat() { |
||||
return new TomcatEmbeddedServletContainerFactory(remotePort); |
||||
} |
||||
|
||||
@Bean |
||||
public DispatcherFilter dispatcherFilter() throws IOException { |
||||
return new DispatcherFilter(dispatcher()); |
||||
} |
||||
|
||||
public Dispatcher dispatcher() throws IOException { |
||||
Dispatcher dispatcher = mock(Dispatcher.class); |
||||
ServerHttpRequest anyRequest = (ServerHttpRequest) any(); |
||||
ServerHttpResponse anyResponse = (ServerHttpResponse) any(); |
||||
given(dispatcher.handle(anyRequest, anyResponse)).willReturn(true); |
||||
return dispatcher; |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue