Merge branch '2.0.x' into 2.1.x
Closes gh-17078
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -53,8 +53,7 @@ public final class RemoteSpringApplication {
|
||||
|
||||
private void run(String[] args) {
|
||||
Restarter.initialize(args, RestartInitializer.NONE);
|
||||
SpringApplication application = new SpringApplication(
|
||||
RemoteClientConfiguration.class);
|
||||
SpringApplication application = new SpringApplication(RemoteClientConfiguration.class);
|
||||
application.setWebApplicationType(WebApplicationType.NONE);
|
||||
application.setBanner(getBanner());
|
||||
application.setInitializers(getInitializers());
|
||||
@@ -80,8 +79,7 @@ public final class RemoteSpringApplication {
|
||||
}
|
||||
|
||||
private Banner getBanner() {
|
||||
ClassPathResource banner = new ClassPathResource("remote-banner.txt",
|
||||
RemoteSpringApplication.class);
|
||||
ClassPathResource banner = new ClassPathResource("remote-banner.txt", RemoteSpringApplication.class);
|
||||
return new ResourceBanner(banner);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -38,8 +38,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class RemoteUrlPropertyExtractor
|
||||
implements ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {
|
||||
class RemoteUrlPropertyExtractor implements ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {
|
||||
|
||||
private static final String NON_OPTION_ARGS = CommandLinePropertySource.DEFAULT_NON_OPTION_ARGS_PROPERTY_NAME;
|
||||
|
||||
|
||||
@@ -39,8 +39,7 @@ class ConditionEvaluationDeltaLoggingListener
|
||||
|
||||
private static final ConcurrentHashMap<String, ConditionEvaluationReport> previousReports = new ConcurrentHashMap<>();
|
||||
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(ConditionEvaluationDeltaLoggingListener.class);
|
||||
private static final Log logger = LogFactory.getLog(ConditionEvaluationDeltaLoggingListener.class);
|
||||
|
||||
private volatile ApplicationContext context;
|
||||
|
||||
@@ -49,25 +48,19 @@ class ConditionEvaluationDeltaLoggingListener
|
||||
if (!event.getApplicationContext().equals(this.context)) {
|
||||
return;
|
||||
}
|
||||
ConditionEvaluationReport report = event.getApplicationContext()
|
||||
.getBean(ConditionEvaluationReport.class);
|
||||
ConditionEvaluationReport previousReport = previousReports
|
||||
.get(event.getApplicationContext().getId());
|
||||
ConditionEvaluationReport report = event.getApplicationContext().getBean(ConditionEvaluationReport.class);
|
||||
ConditionEvaluationReport previousReport = previousReports.get(event.getApplicationContext().getId());
|
||||
if (previousReport != null) {
|
||||
ConditionEvaluationReport delta = report.getDelta(previousReport);
|
||||
if (!delta.getConditionAndOutcomesBySource().isEmpty()
|
||||
|| !delta.getExclusions().isEmpty()
|
||||
if (!delta.getConditionAndOutcomesBySource().isEmpty() || !delta.getExclusions().isEmpty()
|
||||
|| !delta.getUnconditionalClasses().isEmpty()) {
|
||||
if (ConditionEvaluationDeltaLoggingListener.logger.isInfoEnabled()) {
|
||||
ConditionEvaluationDeltaLoggingListener.logger
|
||||
.info("Condition evaluation delta:"
|
||||
+ new ConditionEvaluationReportMessage(delta,
|
||||
"CONDITION EVALUATION DELTA"));
|
||||
ConditionEvaluationDeltaLoggingListener.logger.info("Condition evaluation delta:"
|
||||
+ new ConditionEvaluationReportMessage(delta, "CONDITION EVALUATION DELTA"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
ConditionEvaluationDeltaLoggingListener.logger
|
||||
.info("Condition evaluation unchanged");
|
||||
ConditionEvaluationDeltaLoggingListener.logger.info("Condition evaluation unchanged");
|
||||
}
|
||||
}
|
||||
previousReports.put(event.getApplicationContext().getId(), report);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -60,10 +60,9 @@ import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
public class DevToolsDataSourceAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
NonEmbeddedInMemoryDatabaseShutdownExecutor inMemoryDatabaseShutdownExecutor(
|
||||
DataSource dataSource, DataSourceProperties dataSourceProperties) {
|
||||
return new NonEmbeddedInMemoryDatabaseShutdownExecutor(dataSource,
|
||||
dataSourceProperties);
|
||||
NonEmbeddedInMemoryDatabaseShutdownExecutor inMemoryDatabaseShutdownExecutor(DataSource dataSource,
|
||||
DataSourceProperties dataSourceProperties) {
|
||||
return new NonEmbeddedInMemoryDatabaseShutdownExecutor(dataSource, dataSourceProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,8 +73,7 @@ public class DevToolsDataSourceAutoConfiguration {
|
||||
@Configuration
|
||||
@ConditionalOnClass(LocalContainerEntityManagerFactoryBean.class)
|
||||
@ConditionalOnBean(AbstractEntityManagerFactoryBean.class)
|
||||
static class DatabaseShutdownExecutorJpaDependencyConfiguration
|
||||
extends EntityManagerFactoryDependsOnPostProcessor {
|
||||
static class DatabaseShutdownExecutorJpaDependencyConfiguration extends EntityManagerFactoryDependsOnPostProcessor {
|
||||
|
||||
DatabaseShutdownExecutorJpaDependencyConfiguration() {
|
||||
super("inMemoryDatabaseShutdownExecutor");
|
||||
@@ -83,15 +81,13 @@ public class DevToolsDataSourceAutoConfiguration {
|
||||
|
||||
}
|
||||
|
||||
static final class NonEmbeddedInMemoryDatabaseShutdownExecutor
|
||||
implements DisposableBean {
|
||||
static final class NonEmbeddedInMemoryDatabaseShutdownExecutor implements DisposableBean {
|
||||
|
||||
private final DataSource dataSource;
|
||||
|
||||
private final DataSourceProperties dataSourceProperties;
|
||||
|
||||
NonEmbeddedInMemoryDatabaseShutdownExecutor(DataSource dataSource,
|
||||
DataSourceProperties dataSourceProperties) {
|
||||
NonEmbeddedInMemoryDatabaseShutdownExecutor(DataSource dataSource, DataSourceProperties dataSourceProperties) {
|
||||
this.dataSource = dataSource;
|
||||
this.dataSourceProperties = dataSourceProperties;
|
||||
}
|
||||
@@ -122,8 +118,7 @@ public class DevToolsDataSourceAutoConfiguration {
|
||||
|
||||
H2("jdbc:h2:mem:", "org.h2.Driver", "org.h2.jdbcx.JdbcDataSource"),
|
||||
|
||||
HSQLDB("jdbc:hsqldb:mem:", "org.hsqldb.jdbcDriver",
|
||||
"org.hsqldb.jdbc.JDBCDriver",
|
||||
HSQLDB("jdbc:hsqldb:mem:", "org.hsqldb.jdbcDriver", "org.hsqldb.jdbc.JDBCDriver",
|
||||
"org.hsqldb.jdbc.pool.JDBCXADataSource");
|
||||
|
||||
private final String urlPrefix;
|
||||
@@ -137,18 +132,15 @@ public class DevToolsDataSourceAutoConfiguration {
|
||||
|
||||
boolean matches(DataSourceProperties properties) {
|
||||
String url = properties.getUrl();
|
||||
return (url == null || this.urlPrefix == null
|
||||
|| url.startsWith(this.urlPrefix))
|
||||
&& this.driverClassNames
|
||||
.contains(properties.determineDriverClassName());
|
||||
return (url == null || this.urlPrefix == null || url.startsWith(this.urlPrefix))
|
||||
&& this.driverClassNames.contains(properties.determineDriverClassName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class DevToolsDataSourceCondition extends SpringBootCondition
|
||||
implements ConfigurationCondition {
|
||||
static class DevToolsDataSourceCondition extends SpringBootCondition implements ConfigurationCondition {
|
||||
|
||||
@Override
|
||||
public ConfigurationPhase getConfigurationPhase() {
|
||||
@@ -156,35 +148,24 @@ public class DevToolsDataSourceAutoConfiguration {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
ConditionMessage.Builder message = ConditionMessage
|
||||
.forCondition("DevTools DataSource Condition");
|
||||
String[] dataSourceBeanNames = context.getBeanFactory()
|
||||
.getBeanNamesForType(DataSource.class);
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
ConditionMessage.Builder message = ConditionMessage.forCondition("DevTools DataSource Condition");
|
||||
String[] dataSourceBeanNames = context.getBeanFactory().getBeanNamesForType(DataSource.class);
|
||||
if (dataSourceBeanNames.length != 1) {
|
||||
return ConditionOutcome
|
||||
.noMatch(message.didNotFind("a single DataSource bean").atAll());
|
||||
return ConditionOutcome.noMatch(message.didNotFind("a single DataSource bean").atAll());
|
||||
}
|
||||
if (context.getBeanFactory()
|
||||
.getBeanNamesForType(DataSourceProperties.class).length != 1) {
|
||||
return ConditionOutcome.noMatch(
|
||||
message.didNotFind("a single DataSourceProperties bean").atAll());
|
||||
if (context.getBeanFactory().getBeanNamesForType(DataSourceProperties.class).length != 1) {
|
||||
return ConditionOutcome.noMatch(message.didNotFind("a single DataSourceProperties bean").atAll());
|
||||
}
|
||||
BeanDefinition dataSourceDefinition = context.getRegistry()
|
||||
.getBeanDefinition(dataSourceBeanNames[0]);
|
||||
BeanDefinition dataSourceDefinition = context.getRegistry().getBeanDefinition(dataSourceBeanNames[0]);
|
||||
if (dataSourceDefinition instanceof AnnotatedBeanDefinition
|
||||
&& ((AnnotatedBeanDefinition) dataSourceDefinition)
|
||||
.getFactoryMethodMetadata() != null
|
||||
&& ((AnnotatedBeanDefinition) dataSourceDefinition)
|
||||
.getFactoryMethodMetadata().getDeclaringClassName()
|
||||
.startsWith(DataSourceAutoConfiguration.class.getPackage()
|
||||
.getName() + ".DataSourceConfiguration$")) {
|
||||
return ConditionOutcome
|
||||
.match(message.foundExactly("auto-configured DataSource"));
|
||||
&& ((AnnotatedBeanDefinition) dataSourceDefinition).getFactoryMethodMetadata() != null
|
||||
&& ((AnnotatedBeanDefinition) dataSourceDefinition).getFactoryMethodMetadata()
|
||||
.getDeclaringClassName().startsWith(DataSourceAutoConfiguration.class.getPackage().getName()
|
||||
+ ".DataSourceConfiguration$")) {
|
||||
return ConditionOutcome.match(message.foundExactly("auto-configured DataSource"));
|
||||
}
|
||||
return ConditionOutcome
|
||||
.noMatch(message.didNotFind("an auto-configured DataSource").atAll());
|
||||
return ConditionOutcome.noMatch(message.didNotFind("an auto-configured DataSource").atAll());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -119,8 +119,7 @@ public class DevToolsProperties {
|
||||
allExclude.addAll(StringUtils.commaDelimitedListToSet(this.exclude));
|
||||
}
|
||||
if (StringUtils.hasText(this.additionalExclude)) {
|
||||
allExclude.addAll(
|
||||
StringUtils.commaDelimitedListToSet(this.additionalExclude));
|
||||
allExclude.addAll(StringUtils.commaDelimitedListToSet(this.additionalExclude));
|
||||
}
|
||||
return StringUtils.toStringArray(allExclude);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -44,8 +44,7 @@ class FileWatchingFailureHandler implements FailureHandler {
|
||||
public Outcome handle(Throwable failure) {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
FileSystemWatcher watcher = this.fileSystemWatcherFactory.getFileSystemWatcher();
|
||||
watcher.addSourceFolders(
|
||||
new ClassPathFolders(Restarter.getInstance().getInitialUrls()));
|
||||
watcher.addSourceFolders(new ClassPathFolders(Restarter.getInstance().getInitialUrls()));
|
||||
watcher.addListener(new Listener(latch));
|
||||
watcher.start();
|
||||
try {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -36,8 +36,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
*/
|
||||
class HateoasObjenesisCacheDisabler implements InitializingBean {
|
||||
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(HateoasObjenesisCacheDisabler.class);
|
||||
private static final Log logger = LogFactory.getLog(HateoasObjenesisCacheDisabler.class);
|
||||
|
||||
private static boolean cacheDisabled;
|
||||
|
||||
@@ -55,8 +54,7 @@ class HateoasObjenesisCacheDisabler implements InitializingBean {
|
||||
|
||||
private void doDisableCaching() {
|
||||
try {
|
||||
Class<?> type = ClassUtils.forName(
|
||||
"org.springframework.hateoas.core.DummyInvocationUtils",
|
||||
Class<?> type = ClassUtils.forName("org.springframework.hateoas.core.DummyInvocationUtils",
|
||||
getClass().getClassLoader());
|
||||
removeObjenesisCache(type);
|
||||
}
|
||||
@@ -67,21 +65,17 @@ class HateoasObjenesisCacheDisabler implements InitializingBean {
|
||||
|
||||
private void removeObjenesisCache(Class<?> dummyInvocationUtils) {
|
||||
try {
|
||||
Field objenesisField = ReflectionUtils.findField(dummyInvocationUtils,
|
||||
"OBJENESIS");
|
||||
Field objenesisField = ReflectionUtils.findField(dummyInvocationUtils, "OBJENESIS");
|
||||
if (objenesisField != null) {
|
||||
ReflectionUtils.makeAccessible(objenesisField);
|
||||
Object objenesis = ReflectionUtils.getField(objenesisField, null);
|
||||
Field cacheField = ReflectionUtils.findField(objenesis.getClass(),
|
||||
"cache");
|
||||
Field cacheField = ReflectionUtils.findField(objenesis.getClass(), "cache");
|
||||
ReflectionUtils.makeAccessible(cacheField);
|
||||
ReflectionUtils.setField(cacheField, objenesis, null);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
logger.warn(
|
||||
"Failed to disable Spring HATEOAS's Objenesis cache. ClassCastExceptions may occur",
|
||||
ex);
|
||||
logger.warn("Failed to disable Spring HATEOAS's Objenesis cache. ClassCastExceptions may occur", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,8 +61,7 @@ public class LocalDevToolsAutoConfiguration {
|
||||
* Local LiveReload configuration.
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(prefix = "spring.devtools.livereload", name = "enabled",
|
||||
matchIfMissing = true)
|
||||
@ConditionalOnProperty(prefix = "spring.devtools.livereload", name = "enabled", matchIfMissing = true)
|
||||
static class LiveReloadConfiguration {
|
||||
|
||||
private final DevToolsProperties properties;
|
||||
@@ -80,14 +79,12 @@ public class LocalDevToolsAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public OptionalLiveReloadServer optionalLiveReloadServer(
|
||||
LiveReloadServer liveReloadServer) {
|
||||
public OptionalLiveReloadServer optionalLiveReloadServer(LiveReloadServer liveReloadServer) {
|
||||
return new OptionalLiveReloadServer(liveReloadServer);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LiveReloadServerEventListener liveReloadServerEventListener(
|
||||
OptionalLiveReloadServer liveReloadServer) {
|
||||
public LiveReloadServerEventListener liveReloadServerEventListener(OptionalLiveReloadServer liveReloadServer) {
|
||||
return new LiveReloadServerEventListener(liveReloadServer);
|
||||
}
|
||||
|
||||
@@ -97,10 +94,8 @@ public class LocalDevToolsAutoConfiguration {
|
||||
* Local Restart Configuration.
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(prefix = "spring.devtools.restart", name = "enabled",
|
||||
matchIfMissing = true)
|
||||
static class RestartConfiguration
|
||||
implements ApplicationListener<ClassPathChangedEvent> {
|
||||
@ConditionalOnProperty(prefix = "spring.devtools.restart", name = "enabled", matchIfMissing = true)
|
||||
static class RestartConfiguration implements ApplicationListener<ClassPathChangedEvent> {
|
||||
|
||||
private final DevToolsProperties properties;
|
||||
|
||||
@@ -111,8 +106,7 @@ public class LocalDevToolsAutoConfiguration {
|
||||
@Override
|
||||
public void onApplicationEvent(ClassPathChangedEvent event) {
|
||||
if (event.isRestartRequired()) {
|
||||
Restarter.getInstance().restart(
|
||||
new FileWatchingFailureHandler(fileSystemWatcherFactory()));
|
||||
Restarter.getInstance().restart(new FileWatchingFailureHandler(fileSystemWatcherFactory()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,8 +114,8 @@ public class LocalDevToolsAutoConfiguration {
|
||||
@ConditionalOnMissingBean
|
||||
public ClassPathFileSystemWatcher classPathFileSystemWatcher() {
|
||||
URL[] urls = Restarter.getInstance().getInitialUrls();
|
||||
ClassPathFileSystemWatcher watcher = new ClassPathFileSystemWatcher(
|
||||
fileSystemWatcherFactory(), classPathRestartStrategy(), urls);
|
||||
ClassPathFileSystemWatcher watcher = new ClassPathFileSystemWatcher(fileSystemWatcherFactory(),
|
||||
classPathRestartStrategy(), urls);
|
||||
watcher.setStopWatcherOnRestart(true);
|
||||
return watcher;
|
||||
}
|
||||
@@ -129,8 +123,7 @@ public class LocalDevToolsAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ClassPathRestartStrategy classPathRestartStrategy() {
|
||||
return new PatternClassPathRestartStrategy(
|
||||
this.properties.getRestart().getAllExclude());
|
||||
return new PatternClassPathRestartStrategy(this.properties.getRestart().getAllExclude());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -144,16 +137,15 @@ public class LocalDevToolsAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(prefix = "spring.devtools.restart",
|
||||
name = "log-condition-evaluation-delta", matchIfMissing = true)
|
||||
@ConditionalOnProperty(prefix = "spring.devtools.restart", name = "log-condition-evaluation-delta",
|
||||
matchIfMissing = true)
|
||||
public ConditionEvaluationDeltaLoggingListener conditionEvaluationDeltaLoggingListener() {
|
||||
return new ConditionEvaluationDeltaLoggingListener();
|
||||
}
|
||||
|
||||
private FileSystemWatcher newFileSystemWatcher() {
|
||||
Restart restartProperties = this.properties.getRestart();
|
||||
FileSystemWatcher watcher = new FileSystemWatcher(true,
|
||||
restartProperties.getPollInterval(),
|
||||
FileSystemWatcher watcher = new FileSystemWatcher(true, restartProperties.getPollInterval(),
|
||||
restartProperties.getQuietPeriod());
|
||||
String triggerFile = restartProperties.getTriggerFile();
|
||||
if (StringUtils.hasLength(triggerFile)) {
|
||||
@@ -193,9 +185,8 @@ public class LocalDevToolsAutoConfiguration {
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationEvent event) {
|
||||
if (event instanceof ContextRefreshedEvent
|
||||
|| (event instanceof ClassPathChangedEvent
|
||||
&& !((ClassPathChangedEvent) event).isRestartRequired())) {
|
||||
if (event instanceof ContextRefreshedEvent || (event instanceof ClassPathChangedEvent
|
||||
&& !((ClassPathChangedEvent) event).isRestartRequired())) {
|
||||
this.liveReloadServer.triggerReload();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -54,8 +54,7 @@ public class OptionalLiveReloadServer implements InitializingBean {
|
||||
if (!this.server.isStarted()) {
|
||||
this.server.start();
|
||||
}
|
||||
logger.info(
|
||||
"LiveReload server is running on port " + this.server.getPort());
|
||||
logger.info("LiveReload server is running on port " + this.server.getPort());
|
||||
}
|
||||
catch (Exception ex) {
|
||||
logger.warn("Unable to start LiveReload server");
|
||||
|
||||
@@ -61,15 +61,13 @@ import org.springframework.http.server.ServerHttpRequest;
|
||||
@EnableConfigurationProperties({ ServerProperties.class, DevToolsProperties.class })
|
||||
public class RemoteDevToolsAutoConfiguration {
|
||||
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(RemoteDevToolsAutoConfiguration.class);
|
||||
private static final Log logger = LogFactory.getLog(RemoteDevToolsAutoConfiguration.class);
|
||||
|
||||
private final DevToolsProperties properties;
|
||||
|
||||
private final ServerProperties serverProperties;
|
||||
|
||||
public RemoteDevToolsAutoConfiguration(DevToolsProperties properties,
|
||||
ServerProperties serverProperties) {
|
||||
public RemoteDevToolsAutoConfiguration(DevToolsProperties properties, ServerProperties serverProperties) {
|
||||
this.properties = properties;
|
||||
this.serverProperties = serverProperties;
|
||||
}
|
||||
@@ -78,19 +76,15 @@ public class RemoteDevToolsAutoConfiguration {
|
||||
@ConditionalOnMissingBean
|
||||
public AccessManager remoteDevToolsAccessManager() {
|
||||
RemoteDevToolsProperties remoteProperties = this.properties.getRemote();
|
||||
return new HttpHeaderAccessManager(remoteProperties.getSecretHeaderName(),
|
||||
remoteProperties.getSecret());
|
||||
return new HttpHeaderAccessManager(remoteProperties.getSecretHeaderName(), remoteProperties.getSecret());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HandlerMapper remoteDevToolsHealthCheckHandlerMapper() {
|
||||
Handler handler = new HttpStatusHandler();
|
||||
Servlet servlet = this.serverProperties.getServlet();
|
||||
String servletContextPath = (servlet.getContextPath() != null)
|
||||
? servlet.getContextPath() : "";
|
||||
return new UrlHandlerMapper(
|
||||
servletContextPath + this.properties.getRemote().getContextPath(),
|
||||
handler);
|
||||
String servletContextPath = (servlet.getContextPath() != null) ? servlet.getContextPath() : "";
|
||||
return new UrlHandlerMapper(servletContextPath + this.properties.getRemote().getContextPath(), handler);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -105,8 +99,7 @@ public class RemoteDevToolsAutoConfiguration {
|
||||
* Configuration for remote update and restarts.
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(prefix = "spring.devtools.remote.restart", name = "enabled",
|
||||
matchIfMissing = true)
|
||||
@ConditionalOnProperty(prefix = "spring.devtools.remote.restart", name = "enabled", matchIfMissing = true)
|
||||
static class RemoteRestartConfiguration {
|
||||
|
||||
@Autowired
|
||||
@@ -123,8 +116,7 @@ public class RemoteDevToolsAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public HttpRestartServer remoteRestartHttpRestartServer(
|
||||
SourceFolderUrlFilter sourceFolderUrlFilter) {
|
||||
public HttpRestartServer remoteRestartHttpRestartServer(SourceFolderUrlFilter sourceFolderUrlFilter) {
|
||||
return new HttpRestartServer(sourceFolderUrlFilter);
|
||||
}
|
||||
|
||||
@@ -133,8 +125,7 @@ public class RemoteDevToolsAutoConfiguration {
|
||||
public UrlHandlerMapper remoteRestartHandlerMapper(HttpRestartServer server) {
|
||||
Servlet servlet = this.serverProperties.getServlet();
|
||||
RemoteDevToolsProperties remote = this.properties.getRemote();
|
||||
String servletContextPath = (servlet.getContextPath() != null)
|
||||
? servlet.getContextPath() : "";
|
||||
String servletContextPath = (servlet.getContextPath() != null) ? servlet.getContextPath() : "";
|
||||
String url = servletContextPath + remote.getContextPath() + "/restart";
|
||||
logger.warn("Listening for remote restart updates on " + url);
|
||||
Handler handler = new HttpRestartServerHandler(server);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -41,8 +41,7 @@ public class ClassPathChangedEvent extends ApplicationEvent {
|
||||
* @param changeSet the changed files
|
||||
* @param restartRequired if a restart is required due to the change
|
||||
*/
|
||||
public ClassPathChangedEvent(Object source, Set<ChangedFiles> changeSet,
|
||||
boolean restartRequired) {
|
||||
public ClassPathChangedEvent(Object source, Set<ChangedFiles> changeSet, boolean restartRequired) {
|
||||
super(source);
|
||||
Assert.notNull(changeSet, "ChangeSet must not be null");
|
||||
this.changeSet = changeSet;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -48,8 +48,7 @@ class ClassPathFileChangeListener implements FileChangeListener {
|
||||
* @param fileSystemWatcherToStop the file system watcher to stop on a restart (or
|
||||
* {@code null})
|
||||
*/
|
||||
ClassPathFileChangeListener(ApplicationEventPublisher eventPublisher,
|
||||
ClassPathRestartStrategy restartStrategy,
|
||||
ClassPathFileChangeListener(ApplicationEventPublisher eventPublisher, ClassPathRestartStrategy restartStrategy,
|
||||
FileSystemWatcher fileSystemWatcherToStop) {
|
||||
Assert.notNull(eventPublisher, "EventPublisher must not be null");
|
||||
Assert.notNull(restartStrategy, "RestartStrategy must not be null");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -35,8 +35,7 @@ import org.springframework.util.Assert;
|
||||
* @since 1.3.0
|
||||
* @see ClassPathFileChangeListener
|
||||
*/
|
||||
public class ClassPathFileSystemWatcher
|
||||
implements InitializingBean, DisposableBean, ApplicationContextAware {
|
||||
public class ClassPathFileSystemWatcher implements InitializingBean, DisposableBean, ApplicationContextAware {
|
||||
|
||||
private final FileSystemWatcher fileSystemWatcher;
|
||||
|
||||
@@ -55,8 +54,7 @@ public class ClassPathFileSystemWatcher
|
||||
*/
|
||||
public ClassPathFileSystemWatcher(FileSystemWatcherFactory fileSystemWatcherFactory,
|
||||
ClassPathRestartStrategy restartStrategy, URL[] urls) {
|
||||
Assert.notNull(fileSystemWatcherFactory,
|
||||
"FileSystemWatcherFactory must not be null");
|
||||
Assert.notNull(fileSystemWatcherFactory, "FileSystemWatcherFactory must not be null");
|
||||
Assert.notNull(urls, "Urls must not be null");
|
||||
this.fileSystemWatcher = fileSystemWatcherFactory.getFileSystemWatcher();
|
||||
this.restartStrategy = restartStrategy;
|
||||
@@ -72,8 +70,7 @@ public class ClassPathFileSystemWatcher
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@@ -84,8 +81,8 @@ public class ClassPathFileSystemWatcher
|
||||
if (this.stopWatcherOnRestart) {
|
||||
watcherToStop = this.fileSystemWatcher;
|
||||
}
|
||||
this.fileSystemWatcher.addListener(new ClassPathFileChangeListener(
|
||||
this.applicationContext, this.restartStrategy, watcherToStop));
|
||||
this.fileSystemWatcher.addListener(
|
||||
new ClassPathFileChangeListener(this.applicationContext, this.restartStrategy, watcherToStop));
|
||||
}
|
||||
this.fileSystemWatcher.start();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -41,8 +41,7 @@ public class DevToolsHomePropertiesPostProcessor implements EnvironmentPostProce
|
||||
private static final String FILE_NAME = ".spring-boot-devtools.properties";
|
||||
|
||||
@Override
|
||||
public void postProcessEnvironment(ConfigurableEnvironment environment,
|
||||
SpringApplication application) {
|
||||
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
|
||||
File home = getHomeFolder();
|
||||
File propertyFile = (home != null) ? new File(home, FILE_NAME) : null;
|
||||
if (propertyFile != null && propertyFile.exists() && propertyFile.isFile()) {
|
||||
@@ -50,8 +49,7 @@ public class DevToolsHomePropertiesPostProcessor implements EnvironmentPostProce
|
||||
Properties properties;
|
||||
try {
|
||||
properties = PropertiesLoaderUtils.loadProperties(resource);
|
||||
environment.getPropertySources().addFirst(
|
||||
new PropertiesPropertySource("devtools-local", properties));
|
||||
environment.getPropertySources().addFirst(new PropertiesPropertySource("devtools-local", properties));
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException("Unable to load " + FILE_NAME, ex);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -45,8 +45,7 @@ import org.springframework.util.ClassUtils;
|
||||
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||
public class DevToolsPropertyDefaultsPostProcessor implements EnvironmentPostProcessor {
|
||||
|
||||
private static final Log logger = DevToolsLogFactory
|
||||
.getLog(DevToolsPropertyDefaultsPostProcessor.class);
|
||||
private static final Log logger = DevToolsLogFactory.getLog(DevToolsPropertyDefaultsPostProcessor.class);
|
||||
|
||||
private static final String ENABLED = "spring.devtools.add-properties";
|
||||
|
||||
@@ -77,19 +76,15 @@ public class DevToolsPropertyDefaultsPostProcessor implements EnvironmentPostPro
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessEnvironment(ConfigurableEnvironment environment,
|
||||
SpringApplication application) {
|
||||
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
|
||||
if (isLocalApplication(environment)) {
|
||||
if (canAddProperties(environment)) {
|
||||
logger.info("Devtools property defaults active! Set '" + ENABLED
|
||||
+ "' to 'false' to disable");
|
||||
environment.getPropertySources()
|
||||
.addLast(new MapPropertySource("devtools", PROPERTIES));
|
||||
logger.info("Devtools property defaults active! Set '" + ENABLED + "' to 'false' to disable");
|
||||
environment.getPropertySources().addLast(new MapPropertySource("devtools", PROPERTIES));
|
||||
}
|
||||
if (isWebApplication(environment)
|
||||
&& !environment.containsProperty(WEB_LOGGING)) {
|
||||
logger.info("For additional web related logging consider "
|
||||
+ "setting the '" + WEB_LOGGING + "' property to 'DEBUG'");
|
||||
if (isWebApplication(environment) && !environment.containsProperty(WEB_LOGGING)) {
|
||||
logger.info("For additional web related logging consider " + "setting the '" + WEB_LOGGING
|
||||
+ "' property to 'DEBUG'");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -121,8 +116,7 @@ public class DevToolsPropertyDefaultsPostProcessor implements EnvironmentPostPro
|
||||
|
||||
private boolean isWebApplication(Environment environment) {
|
||||
for (String candidate : WEB_ENVIRONMENT_CLASSES) {
|
||||
Class<?> environmentClass = resolveClassName(candidate,
|
||||
environment.getClass().getClassLoader());
|
||||
Class<?> environmentClass = resolveClassName(candidate, environment.getClass().getClassLoader());
|
||||
if (environmentClass != null && environmentClass.isInstance(environment)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -76,8 +76,8 @@ public final class ChangedFile {
|
||||
File file = this.file.getAbsoluteFile();
|
||||
String folderName = StringUtils.cleanPath(folder.getPath());
|
||||
String fileName = StringUtils.cleanPath(file.getPath());
|
||||
Assert.state(fileName.startsWith(folderName), () -> "The file " + fileName
|
||||
+ " is not contained in the source folder " + folderName);
|
||||
Assert.state(fileName.startsWith(folderName),
|
||||
() -> "The file " + fileName + " is not contained in the source folder " + folderName);
|
||||
return fileName.substring(folderName.length() + 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -71,8 +71,7 @@ public final class ChangedFiles implements Iterable<ChangedFile> {
|
||||
}
|
||||
if (obj instanceof ChangedFiles) {
|
||||
ChangedFiles other = (ChangedFiles) obj;
|
||||
return this.sourceFolder.equals(other.sourceFolder)
|
||||
&& this.files.equals(other.files);
|
||||
return this.sourceFolder.equals(other.sourceFolder) && this.files.equals(other.files);
|
||||
}
|
||||
return super.equals(obj);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -78,8 +78,7 @@ public class FileSystemWatcher {
|
||||
* @param quietPeriod the amount of time required after a change has been detected to
|
||||
* ensure that updates have completed
|
||||
*/
|
||||
public FileSystemWatcher(boolean daemon, Duration pollInterval,
|
||||
Duration quietPeriod) {
|
||||
public FileSystemWatcher(boolean daemon, Duration pollInterval, Duration quietPeriod) {
|
||||
Assert.notNull(pollInterval, "PollInterval must not be null");
|
||||
Assert.notNull(quietPeriod, "QuietPeriod must not be null");
|
||||
Assert.isTrue(pollInterval.toMillis() > 0, "PollInterval must be positive");
|
||||
@@ -157,9 +156,8 @@ public class FileSystemWatcher {
|
||||
if (this.watchThread == null) {
|
||||
Map<File, FolderSnapshot> localFolders = new HashMap<>();
|
||||
localFolders.putAll(this.folders);
|
||||
this.watchThread = new Thread(new Watcher(this.remainingScans,
|
||||
new ArrayList<>(this.listeners), this.triggerFilter,
|
||||
this.pollInterval, this.quietPeriod, localFolders));
|
||||
this.watchThread = new Thread(new Watcher(this.remainingScans, new ArrayList<>(this.listeners),
|
||||
this.triggerFilter, this.pollInterval, this.quietPeriod, localFolders));
|
||||
this.watchThread.setName("File Watcher");
|
||||
this.watchThread.setDaemon(this.daemon);
|
||||
this.watchThread.start();
|
||||
@@ -220,9 +218,8 @@ public class FileSystemWatcher {
|
||||
|
||||
private Map<File, FolderSnapshot> folders;
|
||||
|
||||
private Watcher(AtomicInteger remainingScans, List<FileChangeListener> listeners,
|
||||
FileFilter triggerFilter, long pollInterval, long quietPeriod,
|
||||
Map<File, FolderSnapshot> folders) {
|
||||
private Watcher(AtomicInteger remainingScans, List<FileChangeListener> listeners, FileFilter triggerFilter,
|
||||
long pollInterval, long quietPeriod, Map<File, FolderSnapshot> folders) {
|
||||
this.remainingScans = remainingScans;
|
||||
this.listeners = listeners;
|
||||
this.triggerFilter = triggerFilter;
|
||||
@@ -263,8 +260,7 @@ public class FileSystemWatcher {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isDifferent(Map<File, FolderSnapshot> previous,
|
||||
Map<File, FolderSnapshot> current) {
|
||||
private boolean isDifferent(Map<File, FolderSnapshot> previous, Map<File, FolderSnapshot> current) {
|
||||
if (!previous.keySet().equals(current.keySet())) {
|
||||
return true;
|
||||
}
|
||||
@@ -292,8 +288,7 @@ public class FileSystemWatcher {
|
||||
for (FolderSnapshot snapshot : snapshots) {
|
||||
FolderSnapshot previous = this.folders.get(snapshot.getFolder());
|
||||
updated.put(snapshot.getFolder(), snapshot);
|
||||
ChangedFiles changedFiles = previous.getChangedFiles(snapshot,
|
||||
this.triggerFilter);
|
||||
ChangedFiles changedFiles = previous.getChangedFiles(snapshot, this.triggerFilter);
|
||||
if (!changedFiles.getFiles().isEmpty()) {
|
||||
changeSet.add(changedFiles);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -37,8 +37,7 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
class FolderSnapshot {
|
||||
|
||||
private static final Set<String> DOT_FOLDERS = Collections
|
||||
.unmodifiableSet(new HashSet<>(Arrays.asList(".", "..")));
|
||||
private static final Set<String> DOT_FOLDERS = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(".", "..")));
|
||||
|
||||
private final File folder;
|
||||
|
||||
@@ -74,12 +73,10 @@ class FolderSnapshot {
|
||||
}
|
||||
}
|
||||
|
||||
public ChangedFiles getChangedFiles(FolderSnapshot snapshot,
|
||||
FileFilter triggerFilter) {
|
||||
public ChangedFiles getChangedFiles(FolderSnapshot snapshot, FileFilter triggerFilter) {
|
||||
Assert.notNull(snapshot, "Snapshot must not be null");
|
||||
File folder = this.folder;
|
||||
Assert.isTrue(snapshot.folder.equals(folder),
|
||||
() -> "Snapshot source folder must be '" + folder + "'");
|
||||
Assert.isTrue(snapshot.folder.equals(folder), () -> "Snapshot source folder must be '" + folder + "'");
|
||||
Set<ChangedFile> changes = new LinkedHashSet<>();
|
||||
Map<File, FileSnapshot> previousFiles = getFilesMap();
|
||||
for (FileSnapshot currentFile : snapshot.files) {
|
||||
@@ -89,8 +86,7 @@ class FolderSnapshot {
|
||||
changes.add(new ChangedFile(folder, currentFile.getFile(), Type.ADD));
|
||||
}
|
||||
else if (!previousFile.equals(currentFile)) {
|
||||
changes.add(
|
||||
new ChangedFile(folder, currentFile.getFile(), Type.MODIFY));
|
||||
changes.add(new ChangedFile(folder, currentFile.getFile(), Type.MODIFY));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -40,8 +40,7 @@ class Connection {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(Connection.class);
|
||||
|
||||
private static final Pattern WEBSOCKET_KEY_PATTERN = Pattern
|
||||
.compile("^Sec-WebSocket-Key:(.*)$", Pattern.MULTILINE);
|
||||
private static final Pattern WEBSOCKET_KEY_PATTERN = Pattern.compile("^Sec-WebSocket-Key:(.*)$", Pattern.MULTILINE);
|
||||
|
||||
public static final String WEBSOCKET_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
||||
|
||||
@@ -64,8 +63,7 @@ class Connection {
|
||||
* @param outputStream the socket output stream
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
Connection(Socket socket, InputStream inputStream, OutputStream outputStream)
|
||||
throws IOException {
|
||||
Connection(Socket socket, InputStream inputStream, OutputStream outputStream) throws IOException {
|
||||
this.socket = socket;
|
||||
this.inputStream = new ConnectionInputStream(inputStream);
|
||||
this.outputStream = new ConnectionOutputStream(outputStream);
|
||||
@@ -78,23 +76,19 @@ class Connection {
|
||||
* @throws Exception in case of errors
|
||||
*/
|
||||
public void run() throws Exception {
|
||||
if (this.header.contains("Upgrade: websocket")
|
||||
&& this.header.contains("Sec-WebSocket-Version: 13")) {
|
||||
if (this.header.contains("Upgrade: websocket") && this.header.contains("Sec-WebSocket-Version: 13")) {
|
||||
runWebSocket();
|
||||
}
|
||||
if (this.header.contains("GET /livereload.js")) {
|
||||
this.outputStream.writeHttp(getClass().getResourceAsStream("livereload.js"),
|
||||
"text/javascript");
|
||||
this.outputStream.writeHttp(getClass().getResourceAsStream("livereload.js"), "text/javascript");
|
||||
}
|
||||
}
|
||||
|
||||
private void runWebSocket() throws Exception {
|
||||
String accept = getWebsocketAcceptResponse();
|
||||
this.outputStream.writeHeaders("HTTP/1.1 101 Switching Protocols",
|
||||
"Upgrade: websocket", "Connection: Upgrade",
|
||||
this.outputStream.writeHeaders("HTTP/1.1 101 Switching Protocols", "Upgrade: websocket", "Connection: Upgrade",
|
||||
"Sec-WebSocket-Accept: " + accept);
|
||||
new Frame("{\"command\":\"hello\",\"protocols\":"
|
||||
+ "[\"http://livereload.com/protocols/official-7\"],"
|
||||
new Frame("{\"command\":\"hello\",\"protocols\":" + "[\"http://livereload.com/protocols/official-7\"],"
|
||||
+ "\"serverName\":\"spring-boot\"}").write(this.outputStream);
|
||||
Thread.sleep(100);
|
||||
this.webSocket = true;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -41,8 +41,8 @@ class ConnectionOutputStream extends FilterOutputStream {
|
||||
|
||||
public void writeHttp(InputStream content, String contentType) throws IOException {
|
||||
byte[] bytes = FileCopyUtils.copyToByteArray(content);
|
||||
writeHeaders("HTTP/1.1 200 OK", "Content-Type: " + contentType,
|
||||
"Content-Length: " + bytes.length, "Connection: close");
|
||||
writeHeaders("HTTP/1.1 200 OK", "Content-Type: " + contentType, "Content-Length: " + bytes.length,
|
||||
"Connection: close");
|
||||
write(bytes);
|
||||
flush();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -52,8 +52,7 @@ public class LiveReloadServer {
|
||||
|
||||
private static final int READ_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(4);
|
||||
|
||||
private final ExecutorService executor = Executors
|
||||
.newCachedThreadPool(new WorkerThreadFactory());
|
||||
private final ExecutorService executor = Executors.newCachedThreadPool(new WorkerThreadFactory());
|
||||
|
||||
private final List<Connection> connections = new ArrayList<>();
|
||||
|
||||
@@ -232,8 +231,8 @@ public class LiveReloadServer {
|
||||
* @return a connection
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
protected Connection createConnection(Socket socket, InputStream inputStream,
|
||||
OutputStream outputStream) throws IOException {
|
||||
protected Connection createConnection(Socket socket, InputStream inputStream, OutputStream outputStream)
|
||||
throws IOException {
|
||||
return new Connection(socket, inputStream, outputStream);
|
||||
}
|
||||
|
||||
@@ -271,8 +270,7 @@ public class LiveReloadServer {
|
||||
private void handle() throws Exception {
|
||||
try {
|
||||
try (OutputStream outputStream = this.socket.getOutputStream()) {
|
||||
Connection connection = createConnection(this.socket,
|
||||
this.inputStream, outputStream);
|
||||
Connection connection = createConnection(this.socket, this.inputStream, outputStream);
|
||||
runConnection(connection);
|
||||
}
|
||||
finally {
|
||||
|
||||
@@ -55,14 +55,12 @@ import org.springframework.util.FileCopyUtils;
|
||||
* @author Andy Wilkinson
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class ClassPathChangeUploader
|
||||
implements ApplicationListener<ClassPathChangedEvent> {
|
||||
public class ClassPathChangeUploader implements ApplicationListener<ClassPathChangedEvent> {
|
||||
|
||||
private static final Map<ChangedFile.Type, ClassLoaderFile.Kind> TYPE_MAPPINGS;
|
||||
|
||||
static {
|
||||
Map<ChangedFile.Type, ClassLoaderFile.Kind> map = new EnumMap<>(
|
||||
ChangedFile.Type.class);
|
||||
Map<ChangedFile.Type, ClassLoaderFile.Kind> map = new EnumMap<>(ChangedFile.Type.class);
|
||||
map.put(ChangedFile.Type.ADD, ClassLoaderFile.Kind.ADDED);
|
||||
map.put(ChangedFile.Type.DELETE, ClassLoaderFile.Kind.DELETED);
|
||||
map.put(ChangedFile.Type.MODIFY, ClassLoaderFile.Kind.MODIFIED);
|
||||
@@ -99,21 +97,19 @@ public class ClassPathChangeUploader
|
||||
}
|
||||
}
|
||||
|
||||
private void performUpload(ClassLoaderFiles classLoaderFiles, byte[] bytes)
|
||||
throws IOException {
|
||||
private void performUpload(ClassLoaderFiles classLoaderFiles, byte[] bytes) throws IOException {
|
||||
try {
|
||||
while (true) {
|
||||
try {
|
||||
ClientHttpRequest request = this.requestFactory
|
||||
.createRequest(this.uri, HttpMethod.POST);
|
||||
ClientHttpRequest request = this.requestFactory.createRequest(this.uri, HttpMethod.POST);
|
||||
HttpHeaders headers = request.getHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
|
||||
headers.setContentLength(bytes.length);
|
||||
FileCopyUtils.copy(bytes, request.getBody());
|
||||
ClientHttpResponse response = request.execute();
|
||||
HttpStatus statusCode = response.getStatusCode();
|
||||
Assert.state(statusCode == HttpStatus.OK, () -> "Unexpected "
|
||||
+ statusCode + " response uploading class files");
|
||||
Assert.state(statusCode == HttpStatus.OK,
|
||||
() -> "Unexpected " + statusCode + " response uploading class files");
|
||||
logUpload(classLoaderFiles);
|
||||
return;
|
||||
}
|
||||
@@ -133,8 +129,7 @@ public class ClassPathChangeUploader
|
||||
|
||||
private void logUpload(ClassLoaderFiles classLoaderFiles) {
|
||||
int size = classLoaderFiles.size();
|
||||
logger.info("Uploaded " + size + " class "
|
||||
+ ((size != 1) ? "resources" : "resource"));
|
||||
logger.info("Uploaded " + size + " class " + ((size != 1) ? "resources" : "resource"));
|
||||
}
|
||||
|
||||
private byte[] serialize(ClassLoaderFiles classLoaderFiles) throws IOException {
|
||||
@@ -145,26 +140,21 @@ public class ClassPathChangeUploader
|
||||
return outputStream.toByteArray();
|
||||
}
|
||||
|
||||
private ClassLoaderFiles getClassLoaderFiles(ClassPathChangedEvent event)
|
||||
throws IOException {
|
||||
private ClassLoaderFiles getClassLoaderFiles(ClassPathChangedEvent event) throws IOException {
|
||||
ClassLoaderFiles files = new ClassLoaderFiles();
|
||||
for (ChangedFiles changedFiles : event.getChangeSet()) {
|
||||
String sourceFolder = changedFiles.getSourceFolder().getAbsolutePath();
|
||||
for (ChangedFile changedFile : changedFiles) {
|
||||
files.addFile(sourceFolder, changedFile.getRelativeName(),
|
||||
asClassLoaderFile(changedFile));
|
||||
files.addFile(sourceFolder, changedFile.getRelativeName(), asClassLoaderFile(changedFile));
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
private ClassLoaderFile asClassLoaderFile(ChangedFile changedFile)
|
||||
throws IOException {
|
||||
private ClassLoaderFile asClassLoaderFile(ChangedFile changedFile) throws IOException {
|
||||
ClassLoaderFile.Kind kind = TYPE_MAPPINGS.get(changedFile.getType());
|
||||
byte[] bytes = (kind != Kind.DELETED)
|
||||
? FileCopyUtils.copyToByteArray(changedFile.getFile()) : null;
|
||||
long lastModified = (kind != Kind.DELETED) ? changedFile.getFile().lastModified()
|
||||
: System.currentTimeMillis();
|
||||
byte[] bytes = (kind != Kind.DELETED) ? FileCopyUtils.copyToByteArray(changedFile.getFile()) : null;
|
||||
long lastModified = (kind != Kind.DELETED) ? changedFile.getFile().lastModified() : System.currentTimeMillis();
|
||||
return new ClassLoaderFile(kind, lastModified, bytes);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -59,8 +59,8 @@ class DelayedLiveReloadTrigger implements Runnable {
|
||||
|
||||
private long timeout = TIMEOUT;
|
||||
|
||||
DelayedLiveReloadTrigger(OptionalLiveReloadServer liveReloadServer,
|
||||
ClientHttpRequestFactory requestFactory, String url) {
|
||||
DelayedLiveReloadTrigger(OptionalLiveReloadServer liveReloadServer, ClientHttpRequestFactory requestFactory,
|
||||
String url) {
|
||||
Assert.notNull(liveReloadServer, "LiveReloadServer must not be null");
|
||||
Assert.notNull(requestFactory, "RequestFactory must not be null");
|
||||
Assert.hasLength(url, "URL must not be empty");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -51,8 +51,8 @@ public class HttpHeaderInterceptor implements ClientHttpRequestInterceptor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientHttpResponse intercept(HttpRequest request, byte[] body,
|
||||
ClientHttpRequestExecution execution) throws IOException {
|
||||
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
|
||||
throws IOException {
|
||||
request.getHeaders().add(this.name, this.value);
|
||||
return execution.execute(request, body);
|
||||
}
|
||||
|
||||
@@ -89,13 +89,12 @@ public class RemoteClientConfiguration implements InitializingBean {
|
||||
|
||||
@Bean
|
||||
public ClientHttpRequestFactory clientHttpRequestFactory() {
|
||||
List<ClientHttpRequestInterceptor> interceptors = Arrays
|
||||
.asList(getSecurityInterceptor());
|
||||
List<ClientHttpRequestInterceptor> interceptors = Arrays.asList(getSecurityInterceptor());
|
||||
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
|
||||
Proxy proxy = this.properties.getRemote().getProxy();
|
||||
if (proxy.getHost() != null && proxy.getPort() != null) {
|
||||
requestFactory.setProxy(new java.net.Proxy(Type.HTTP,
|
||||
new InetSocketAddress(proxy.getHost(), proxy.getPort())));
|
||||
requestFactory
|
||||
.setProxy(new java.net.Proxy(Type.HTTP, new InetSocketAddress(proxy.getHost(), proxy.getPort())));
|
||||
}
|
||||
return new InterceptingClientHttpRequestFactory(requestFactory, interceptors);
|
||||
}
|
||||
@@ -105,8 +104,7 @@ public class RemoteClientConfiguration implements InitializingBean {
|
||||
String secretHeaderName = remoteProperties.getSecretHeaderName();
|
||||
String secret = remoteProperties.getSecret();
|
||||
Assert.state(secret != null,
|
||||
"The environment value 'spring.devtools.remote.secret' "
|
||||
+ "is required to secure your connection.");
|
||||
"The environment value 'spring.devtools.remote.secret' " + "is required to secure your connection.");
|
||||
return new HttpHeaderInterceptor(secretHeaderName, secret);
|
||||
}
|
||||
|
||||
@@ -130,10 +128,8 @@ public class RemoteClientConfiguration implements InitializingBean {
|
||||
* LiveReload configuration.
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(prefix = "spring.devtools.livereload", name = "enabled",
|
||||
matchIfMissing = true)
|
||||
static class LiveReloadConfiguration
|
||||
implements ApplicationListener<ClassPathChangedEvent> {
|
||||
@ConditionalOnProperty(prefix = "spring.devtools.livereload", name = "enabled", matchIfMissing = true)
|
||||
static class LiveReloadConfiguration implements ApplicationListener<ClassPathChangedEvent> {
|
||||
|
||||
@Autowired
|
||||
private DevToolsProperties properties;
|
||||
@@ -160,8 +156,8 @@ public class RemoteClientConfiguration implements InitializingBean {
|
||||
@Override
|
||||
public void onApplicationEvent(ClassPathChangedEvent event) {
|
||||
String url = this.remoteUrl + this.properties.getRemote().getContextPath();
|
||||
this.executor.execute(new DelayedLiveReloadTrigger(optionalLiveReloadServer(),
|
||||
this.clientHttpRequestFactory, url));
|
||||
this.executor.execute(
|
||||
new DelayedLiveReloadTrigger(optionalLiveReloadServer(), this.clientHttpRequestFactory, url));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -179,8 +175,7 @@ public class RemoteClientConfiguration implements InitializingBean {
|
||||
* Client configuration for remote update and restarts.
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(prefix = "spring.devtools.remote.restart", name = "enabled",
|
||||
matchIfMissing = true)
|
||||
@ConditionalOnProperty(prefix = "spring.devtools.remote.restart", name = "enabled", matchIfMissing = true)
|
||||
static class RemoteRestartClientConfiguration {
|
||||
|
||||
@Autowired
|
||||
@@ -196,8 +191,7 @@ public class RemoteClientConfiguration implements InitializingBean {
|
||||
if (urls == null) {
|
||||
urls = new URL[0];
|
||||
}
|
||||
return new ClassPathFileSystemWatcher(getFileSystemWatcherFactory(),
|
||||
classPathRestartStrategy(), urls);
|
||||
return new ClassPathFileSystemWatcher(getFileSystemWatcherFactory(), classPathRestartStrategy(), urls);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -207,8 +201,7 @@ public class RemoteClientConfiguration implements InitializingBean {
|
||||
|
||||
private FileSystemWatcher newFileSystemWatcher() {
|
||||
Restart restartProperties = this.properties.getRestart();
|
||||
FileSystemWatcher watcher = new FileSystemWatcher(true,
|
||||
restartProperties.getPollInterval(),
|
||||
FileSystemWatcher watcher = new FileSystemWatcher(true, restartProperties.getPollInterval(),
|
||||
restartProperties.getQuietPeriod());
|
||||
String triggerFile = restartProperties.getTriggerFile();
|
||||
if (StringUtils.hasLength(triggerFile)) {
|
||||
@@ -219,15 +212,12 @@ public class RemoteClientConfiguration implements InitializingBean {
|
||||
|
||||
@Bean
|
||||
public ClassPathRestartStrategy classPathRestartStrategy() {
|
||||
return new PatternClassPathRestartStrategy(
|
||||
this.properties.getRestart().getAllExclude());
|
||||
return new PatternClassPathRestartStrategy(this.properties.getRestart().getAllExclude());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ClassPathChangeUploader classPathChangeUploader(
|
||||
ClientHttpRequestFactory requestFactory) {
|
||||
String url = this.remoteUrl + this.properties.getRemote().getContextPath()
|
||||
+ "/restart";
|
||||
public ClassPathChangeUploader classPathChangeUploader(ClientHttpRequestFactory requestFactory) {
|
||||
String url = this.remoteUrl + this.properties.getRemote().getContextPath() + "/restart";
|
||||
return new ClassPathChangeUploader(url, requestFactory);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -57,8 +57,7 @@ public class Dispatcher {
|
||||
* @return {@code true} if the request was dispatched
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
public boolean handle(ServerHttpRequest request, ServerHttpResponse response)
|
||||
throws IOException {
|
||||
public boolean handle(ServerHttpRequest request, ServerHttpResponse response) throws IOException {
|
||||
for (HandlerMapper mapper : this.mappers) {
|
||||
Handler handler = mapper.getHandler(request);
|
||||
if (handler != null) {
|
||||
@@ -69,8 +68,7 @@ public class Dispatcher {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void handle(Handler handler, ServerHttpRequest request,
|
||||
ServerHttpResponse response) throws IOException {
|
||||
private void handle(Handler handler, ServerHttpRequest request, ServerHttpResponse response) throws IOException {
|
||||
if (!this.accessManager.isAllowed(request)) {
|
||||
response.setStatusCode(HttpStatus.FORBIDDEN);
|
||||
return;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -54,10 +54,9 @@ public class DispatcherFilter implements Filter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
if (request instanceof HttpServletRequest
|
||||
&& response instanceof HttpServletResponse) {
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) {
|
||||
doFilter((HttpServletRequest) request, (HttpServletResponse) response, chain);
|
||||
}
|
||||
else {
|
||||
@@ -65,8 +64,8 @@ public class DispatcherFilter implements Filter {
|
||||
}
|
||||
}
|
||||
|
||||
private void doFilter(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
ServerHttpRequest serverRequest = new ServletServerHttpRequest(request);
|
||||
ServerHttpResponse serverResponse = new ServletServerHttpResponse(response);
|
||||
if (!this.dispatcher.handle(serverRequest, serverResponse)) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -36,7 +36,6 @@ public interface Handler {
|
||||
* @param response the response
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
void handle(ServerHttpRequest request, ServerHttpResponse response)
|
||||
throws IOException;
|
||||
void handle(ServerHttpRequest request, ServerHttpResponse response) throws IOException;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -51,8 +51,7 @@ public class HttpStatusHandler implements Handler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(ServerHttpRequest request, ServerHttpResponse response)
|
||||
throws IOException {
|
||||
public void handle(ServerHttpRequest request, ServerHttpResponse response) throws IOException {
|
||||
response.setStatusCode(this.status);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -54,8 +54,7 @@ final class ChangeableUrls implements Iterable<URL> {
|
||||
DevToolsSettings settings = DevToolsSettings.get();
|
||||
List<URL> reloadableUrls = new ArrayList<>(urls.length);
|
||||
for (URL url : urls) {
|
||||
if ((settings.isRestartInclude(url) || isFolderUrl(url.toString()))
|
||||
&& !settings.isRestartExclude(url)) {
|
||||
if ((settings.isRestartInclude(url) || isFolderUrl(url.toString())) && !settings.isRestartExclude(url)) {
|
||||
reloadableUrls.add(url);
|
||||
}
|
||||
}
|
||||
@@ -104,9 +103,7 @@ final class ChangeableUrls implements Iterable<URL> {
|
||||
if (classLoader instanceof URLClassLoader) {
|
||||
return ((URLClassLoader) classLoader).getURLs();
|
||||
}
|
||||
return Stream
|
||||
.of(ManagementFactory.getRuntimeMXBean().getClassPath()
|
||||
.split(File.pathSeparator))
|
||||
return Stream.of(ManagementFactory.getRuntimeMXBean().getClassPath().split(File.pathSeparator))
|
||||
.map(ChangeableUrls::toURL).toArray(URL[]::new);
|
||||
}
|
||||
|
||||
@@ -115,8 +112,7 @@ final class ChangeableUrls implements Iterable<URL> {
|
||||
return new File(classPathEntry).toURI().toURL();
|
||||
}
|
||||
catch (MalformedURLException ex) {
|
||||
throw new IllegalArgumentException(
|
||||
"URL could not be created from '" + classPathEntry + "'", ex);
|
||||
throw new IllegalArgumentException("URL could not be created from '" + classPathEntry + "'", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,9 +125,7 @@ final class ChangeableUrls implements Iterable<URL> {
|
||||
return getUrlsFromManifestClassPathAttribute(url, jarFile);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException(
|
||||
"Failed to read Class-Path attribute from manifest of jar " + url,
|
||||
ex);
|
||||
throw new IllegalStateException("Failed to read Class-Path attribute from manifest of jar " + url, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,14 +142,12 @@ final class ChangeableUrls implements Iterable<URL> {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static List<URL> getUrlsFromManifestClassPathAttribute(URL jarUrl,
|
||||
JarFile jarFile) throws IOException {
|
||||
private static List<URL> getUrlsFromManifestClassPathAttribute(URL jarUrl, JarFile jarFile) throws IOException {
|
||||
Manifest manifest = jarFile.getManifest();
|
||||
if (manifest == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
String classPath = manifest.getMainAttributes()
|
||||
.getValue(Attributes.Name.CLASS_PATH);
|
||||
String classPath = manifest.getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
|
||||
if (!StringUtils.hasText(classPath)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@@ -173,8 +165,7 @@ final class ChangeableUrls implements Iterable<URL> {
|
||||
}
|
||||
}
|
||||
catch (MalformedURLException ex) {
|
||||
throw new IllegalStateException(
|
||||
"Class-Path attribute contains malformed URL", ex);
|
||||
throw new IllegalStateException("Class-Path attribute contains malformed URL", ex);
|
||||
}
|
||||
}
|
||||
if (!nonExistentEntries.isEmpty()) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -57,11 +57,9 @@ import org.springframework.web.context.support.ServletContextResourcePatternReso
|
||||
*/
|
||||
final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternResolver {
|
||||
|
||||
private static final String[] LOCATION_PATTERN_PREFIXES = { CLASSPATH_ALL_URL_PREFIX,
|
||||
CLASSPATH_URL_PREFIX };
|
||||
private static final String[] LOCATION_PATTERN_PREFIXES = { CLASSPATH_ALL_URL_PREFIX, CLASSPATH_URL_PREFIX };
|
||||
|
||||
private static final String WEB_CONTEXT_CLASS = "org.springframework.web.context."
|
||||
+ "WebApplicationContext";
|
||||
private static final String WEB_CONTEXT_CLASS = "org.springframework.web.context." + "WebApplicationContext";
|
||||
|
||||
private final ResourcePatternResolver patternResolverDelegate;
|
||||
|
||||
@@ -69,17 +67,14 @@ final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternRe
|
||||
|
||||
private final ClassLoaderFiles classLoaderFiles;
|
||||
|
||||
ClassLoaderFilesResourcePatternResolver(ApplicationContext applicationContext,
|
||||
ClassLoaderFiles classLoaderFiles) {
|
||||
ClassLoaderFilesResourcePatternResolver(ApplicationContext applicationContext, ClassLoaderFiles classLoaderFiles) {
|
||||
this.classLoaderFiles = classLoaderFiles;
|
||||
this.patternResolverDelegate = getResourcePatternResolverFactory()
|
||||
.getResourcePatternResolver(applicationContext,
|
||||
retrieveResourceLoader(applicationContext));
|
||||
.getResourcePatternResolver(applicationContext, retrieveResourceLoader(applicationContext));
|
||||
}
|
||||
|
||||
private ResourceLoader retrieveResourceLoader(ApplicationContext applicationContext) {
|
||||
Field field = ReflectionUtils.findField(applicationContext.getClass(),
|
||||
"resourceLoader", ResourceLoader.class);
|
||||
Field field = ReflectionUtils.findField(applicationContext.getClass(), "resourceLoader", ResourceLoader.class);
|
||||
if (field == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -111,8 +106,7 @@ final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternRe
|
||||
@Override
|
||||
public Resource[] getResources(String locationPattern) throws IOException {
|
||||
List<Resource> resources = new ArrayList<>();
|
||||
Resource[] candidates = this.patternResolverDelegate
|
||||
.getResources(locationPattern);
|
||||
Resource[] candidates = this.patternResolverDelegate.getResources(locationPattern);
|
||||
for (Resource candidate : candidates) {
|
||||
if (!isDeleted(candidate)) {
|
||||
resources.add(candidate);
|
||||
@@ -122,18 +116,15 @@ final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternRe
|
||||
return resources.toArray(new Resource[0]);
|
||||
}
|
||||
|
||||
private List<Resource> getAdditionalResources(String locationPattern)
|
||||
throws MalformedURLException {
|
||||
private List<Resource> getAdditionalResources(String locationPattern) throws MalformedURLException {
|
||||
List<Resource> additionalResources = new ArrayList<>();
|
||||
String trimmedLocationPattern = trimLocationPattern(locationPattern);
|
||||
for (SourceFolder sourceFolder : this.classLoaderFiles.getSourceFolders()) {
|
||||
for (Entry<String, ClassLoaderFile> entry : sourceFolder.getFilesEntrySet()) {
|
||||
String name = entry.getKey();
|
||||
ClassLoaderFile file = entry.getValue();
|
||||
if (file.getKind() != Kind.DELETED
|
||||
&& this.antPathMatcher.match(trimmedLocationPattern, name)) {
|
||||
URL url = new URL("reloaded", null, -1, "/" + name,
|
||||
new ClassLoaderFileURLStreamHandler(file));
|
||||
if (file.getKind() != Kind.DELETED && this.antPathMatcher.match(trimmedLocationPattern, name)) {
|
||||
URL url = new URL("reloaded", null, -1, "/" + name, new ClassLoaderFileURLStreamHandler(file));
|
||||
UrlResource resource = new UrlResource(url);
|
||||
additionalResources.add(resource);
|
||||
}
|
||||
@@ -163,8 +154,7 @@ final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternRe
|
||||
}
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException(
|
||||
"Failed to retrieve URI from '" + resource + "'", ex);
|
||||
throw new IllegalStateException("Failed to retrieve URI from '" + resource + "'", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -205,8 +195,8 @@ final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternRe
|
||||
*/
|
||||
private static class ResourcePatternResolverFactory {
|
||||
|
||||
public ResourcePatternResolver getResourcePatternResolver(
|
||||
ApplicationContext applicationContext, ResourceLoader resourceLoader) {
|
||||
public ResourcePatternResolver getResourcePatternResolver(ApplicationContext applicationContext,
|
||||
ResourceLoader resourceLoader) {
|
||||
if (resourceLoader == null) {
|
||||
resourceLoader = new DefaultResourceLoader();
|
||||
copyProtocolResolvers(applicationContext, resourceLoader);
|
||||
@@ -223,8 +213,7 @@ final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternRe
|
||||
}
|
||||
}
|
||||
|
||||
protected final void copyProtocolResolvers(DefaultResourceLoader source,
|
||||
DefaultResourceLoader destination) {
|
||||
protected final void copyProtocolResolvers(DefaultResourceLoader source, DefaultResourceLoader destination) {
|
||||
for (ProtocolResolver resolver : source.getProtocolResolvers()) {
|
||||
destination.addProtocolResolver(resolver);
|
||||
}
|
||||
@@ -236,24 +225,21 @@ final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternRe
|
||||
* {@link ResourcePatternResolverFactory} to be used when the classloader can access
|
||||
* {@link WebApplicationContext}.
|
||||
*/
|
||||
private static class WebResourcePatternResolverFactory
|
||||
extends ResourcePatternResolverFactory {
|
||||
private static class WebResourcePatternResolverFactory extends ResourcePatternResolverFactory {
|
||||
|
||||
@Override
|
||||
public ResourcePatternResolver getResourcePatternResolver(
|
||||
ApplicationContext applicationContext, ResourceLoader resourceLoader) {
|
||||
public ResourcePatternResolver getResourcePatternResolver(ApplicationContext applicationContext,
|
||||
ResourceLoader resourceLoader) {
|
||||
if (applicationContext instanceof WebApplicationContext) {
|
||||
return getResourcePatternResolver(
|
||||
(WebApplicationContext) applicationContext, resourceLoader);
|
||||
return getResourcePatternResolver((WebApplicationContext) applicationContext, resourceLoader);
|
||||
}
|
||||
return super.getResourcePatternResolver(applicationContext, resourceLoader);
|
||||
}
|
||||
|
||||
private ResourcePatternResolver getResourcePatternResolver(
|
||||
WebApplicationContext applicationContext, ResourceLoader resourceLoader) {
|
||||
private ResourcePatternResolver getResourcePatternResolver(WebApplicationContext applicationContext,
|
||||
ResourceLoader resourceLoader) {
|
||||
if (resourceLoader == null) {
|
||||
resourceLoader = new WebApplicationContextResourceLoader(
|
||||
applicationContext);
|
||||
resourceLoader = new WebApplicationContextResourceLoader(applicationContext);
|
||||
copyProtocolResolvers(applicationContext, resourceLoader);
|
||||
}
|
||||
return new ServletContextResourcePatternResolver(resourceLoader);
|
||||
@@ -266,8 +252,7 @@ final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternRe
|
||||
* {@link ResourceLoader} that optionally supports {@link ServletContextResource
|
||||
* ServletContextResources}.
|
||||
*/
|
||||
private static class WebApplicationContextResourceLoader
|
||||
extends DefaultResourceLoader {
|
||||
private static class WebApplicationContextResourceLoader extends DefaultResourceLoader {
|
||||
|
||||
private final WebApplicationContext applicationContext;
|
||||
|
||||
@@ -278,8 +263,7 @@ final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternRe
|
||||
@Override
|
||||
protected Resource getResourceByPath(String path) {
|
||||
if (this.applicationContext.getServletContext() != null) {
|
||||
return new ServletContextResource(
|
||||
this.applicationContext.getServletContext(), path);
|
||||
return new ServletContextResource(this.applicationContext.getServletContext(), path);
|
||||
}
|
||||
return super.getResourceByPath(path);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -63,8 +63,8 @@ public class DefaultRestartInitializer implements RestartInitializer {
|
||||
* @return {@code true} if the thread is a main invocation
|
||||
*/
|
||||
protected boolean isMain(Thread thread) {
|
||||
return thread.getName().equals("main") && thread.getContextClassLoader()
|
||||
.getClass().getName().contains("AppClassLoader");
|
||||
return thread.getName().equals("main")
|
||||
&& thread.getContextClassLoader().getClass().getName().contains("AppClassLoader");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -32,10 +32,8 @@ import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
class OnInitializedRestarterCondition extends SpringBootCondition {
|
||||
|
||||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
ConditionMessage.Builder message = ConditionMessage
|
||||
.forCondition("Initialized Restarter Condition");
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
ConditionMessage.Builder message = ConditionMessage.forCondition("Initialized Restarter Condition");
|
||||
Restarter restarter = getRestarter();
|
||||
if (restarter == null) {
|
||||
return ConditionOutcome.noMatch(message.because("unavailable"));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -35,8 +35,7 @@ import org.springframework.core.Ordered;
|
||||
* @since 1.3.0
|
||||
* @see Restarter
|
||||
*/
|
||||
public class RestartApplicationListener
|
||||
implements ApplicationListener<ApplicationEvent>, Ordered {
|
||||
public class RestartApplicationListener implements ApplicationListener<ApplicationEvent>, Ordered {
|
||||
|
||||
private static final String ENABLED_PROPERTY = "spring.devtools.restart.enabled";
|
||||
|
||||
@@ -52,8 +51,7 @@ public class RestartApplicationListener
|
||||
if (event instanceof ApplicationPreparedEvent) {
|
||||
onApplicationPreparedEvent((ApplicationPreparedEvent) event);
|
||||
}
|
||||
if (event instanceof ApplicationReadyEvent
|
||||
|| event instanceof ApplicationFailedEvent) {
|
||||
if (event instanceof ApplicationReadyEvent || event instanceof ApplicationFailedEvent) {
|
||||
Restarter.getInstance().finish();
|
||||
}
|
||||
if (event instanceof ApplicationFailedEvent) {
|
||||
@@ -70,14 +68,12 @@ public class RestartApplicationListener
|
||||
DefaultRestartInitializer initializer = new DefaultRestartInitializer();
|
||||
boolean restartOnInitialize = !AgentReloader.isActive();
|
||||
if (!restartOnInitialize) {
|
||||
logger.info(
|
||||
"Restart disabled due to an agent-based reloader being active");
|
||||
logger.info("Restart disabled due to an agent-based reloader being active");
|
||||
}
|
||||
Restarter.initialize(args, false, initializer, restartOnInitialize);
|
||||
}
|
||||
else {
|
||||
logger.info("Restart disabled due to System property '" + ENABLED_PROPERTY
|
||||
+ "' being set to false");
|
||||
logger.info("Restart disabled due to System property '" + ENABLED_PROPERTY + "' being set to false");
|
||||
Restarter.disable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -27,8 +27,7 @@ import org.springframework.context.ConfigurableApplicationContext;
|
||||
* @author Phillip Webb
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class RestartScopeInitializer
|
||||
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||
public class RestartScopeInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||
|
||||
@Override
|
||||
public void initialize(ConfigurableApplicationContext applicationContext) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -129,8 +129,7 @@ public class Restarter {
|
||||
* @param initializer the restart initializer
|
||||
* @see #initialize(String[])
|
||||
*/
|
||||
protected Restarter(Thread thread, String[] args, boolean forceReferenceCleanup,
|
||||
RestartInitializer initializer) {
|
||||
protected Restarter(Thread thread, String[] args, boolean forceReferenceCleanup, RestartInitializer initializer) {
|
||||
Assert.notNull(thread, "Thread must not be null");
|
||||
Assert.notNull(args, "Args must not be null");
|
||||
Assert.notNull(initializer, "Initializer must not be null");
|
||||
@@ -277,11 +276,9 @@ public class Restarter {
|
||||
Assert.notNull(this.mainClassName, "Unable to find the main class to restart");
|
||||
URL[] urls = this.urls.toArray(new URL[0]);
|
||||
ClassLoaderFiles updatedFiles = new ClassLoaderFiles(this.classLoaderFiles);
|
||||
ClassLoader classLoader = new RestartClassLoader(this.applicationClassLoader,
|
||||
urls, updatedFiles, this.logger);
|
||||
ClassLoader classLoader = new RestartClassLoader(this.applicationClassLoader, urls, updatedFiles, this.logger);
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug("Starting application " + this.mainClassName + " with URLs "
|
||||
+ Arrays.asList(urls));
|
||||
this.logger.debug("Starting application " + this.mainClassName + " with URLs " + Arrays.asList(urls));
|
||||
}
|
||||
return relaunch(classLoader);
|
||||
}
|
||||
@@ -293,8 +290,8 @@ public class Restarter {
|
||||
* @throws Exception in case of errors
|
||||
*/
|
||||
protected Throwable relaunch(ClassLoader classLoader) throws Exception {
|
||||
RestartLauncher launcher = new RestartLauncher(classLoader, this.mainClassName,
|
||||
this.args, this.exceptionHandler);
|
||||
RestartLauncher launcher = new RestartLauncher(classLoader, this.mainClassName, this.args,
|
||||
this.exceptionHandler);
|
||||
launcher.start();
|
||||
launcher.join();
|
||||
return launcher.getError();
|
||||
@@ -363,8 +360,7 @@ public class Restarter {
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug("Unable to clear field " + className + " " + fieldName,
|
||||
ex);
|
||||
this.logger.debug("Unable to clear field " + className + " " + fieldName, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -389,8 +385,7 @@ public class Restarter {
|
||||
}
|
||||
|
||||
private boolean isFromRestartClassLoader(Object object) {
|
||||
return (object instanceof Class
|
||||
&& ((Class<?>) object).getClassLoader() instanceof RestartClassLoader);
|
||||
return (object instanceof Class && ((Class<?>) object).getClassLoader() instanceof RestartClassLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -415,8 +410,7 @@ public class Restarter {
|
||||
void finish() {
|
||||
synchronized (this.monitor) {
|
||||
if (!isFinished()) {
|
||||
this.logger = DeferredLog.replay(this.logger,
|
||||
LogFactory.getLog(getClass()));
|
||||
this.logger = DeferredLog.replay(this.logger, LogFactory.getLog(getClass()));
|
||||
this.finished = true;
|
||||
}
|
||||
}
|
||||
@@ -445,8 +439,8 @@ public class Restarter {
|
||||
}
|
||||
|
||||
private void prepare(GenericApplicationContext applicationContext) {
|
||||
ResourceLoader resourceLoader = new ClassLoaderFilesResourcePatternResolver(
|
||||
applicationContext, this.classLoaderFiles);
|
||||
ResourceLoader resourceLoader = new ClassLoaderFilesResourcePatternResolver(applicationContext,
|
||||
this.classLoaderFiles);
|
||||
applicationContext.setResourceLoader(resourceLoader);
|
||||
}
|
||||
|
||||
@@ -531,8 +525,7 @@ public class Restarter {
|
||||
* @param initializer the restart initializer
|
||||
* @see #initialize(String[], boolean, RestartInitializer)
|
||||
*/
|
||||
public static void initialize(String[] args, boolean forceReferenceCleanup,
|
||||
RestartInitializer initializer) {
|
||||
public static void initialize(String[] args, boolean forceReferenceCleanup, RestartInitializer initializer) {
|
||||
initialize(args, forceReferenceCleanup, initializer, true);
|
||||
}
|
||||
|
||||
@@ -548,13 +541,12 @@ public class Restarter {
|
||||
* @param restartOnInitialize if the restarter should be restarted immediately when
|
||||
* the {@link RestartInitializer} returns non {@code null} results
|
||||
*/
|
||||
public static void initialize(String[] args, boolean forceReferenceCleanup,
|
||||
RestartInitializer initializer, boolean restartOnInitialize) {
|
||||
public static void initialize(String[] args, boolean forceReferenceCleanup, RestartInitializer initializer,
|
||||
boolean restartOnInitialize) {
|
||||
Restarter localInstance = null;
|
||||
synchronized (INSTANCE_MONITOR) {
|
||||
if (instance == null) {
|
||||
localInstance = new Restarter(Thread.currentThread(), args,
|
||||
forceReferenceCleanup, initializer);
|
||||
localInstance = new Restarter(Thread.currentThread(), args, forceReferenceCleanup, initializer);
|
||||
instance = localInstance;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -56,8 +56,7 @@ public class ClassLoaderFile implements Serializable {
|
||||
public ClassLoaderFile(Kind kind, long lastModified, byte[] contents) {
|
||||
Assert.notNull(kind, "Kind must not be null");
|
||||
Assert.isTrue((kind != Kind.DELETED) ? contents != null : contents == null,
|
||||
() -> "Contents must " + ((kind != Kind.DELETED) ? "not " : "")
|
||||
+ "be null");
|
||||
() -> "Contents must " + ((kind != Kind.DELETED) ? "not " : "") + "be null");
|
||||
this.kind = kind;
|
||||
this.lastModified = lastModified;
|
||||
this.contents = contents;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -54,8 +54,7 @@ public class ClassLoaderFileURLStreamHandler extends URLStreamHandler {
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return new ByteArrayInputStream(
|
||||
ClassLoaderFileURLStreamHandler.this.file.getContents());
|
||||
return new ByteArrayInputStream(ClassLoaderFileURLStreamHandler.this.file.getContents());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -61,8 +61,7 @@ public class RestartClassLoader extends URLClassLoader implements SmartClassLoad
|
||||
* URLs were created.
|
||||
* @param urls the urls managed by the classloader
|
||||
*/
|
||||
public RestartClassLoader(ClassLoader parent, URL[] urls,
|
||||
ClassLoaderFileRepository updatedFiles) {
|
||||
public RestartClassLoader(ClassLoader parent, URL[] urls, ClassLoaderFileRepository updatedFiles) {
|
||||
this(parent, urls, updatedFiles, LogFactory.getLog(RestartClassLoader.class));
|
||||
}
|
||||
|
||||
@@ -74,8 +73,7 @@ public class RestartClassLoader extends URLClassLoader implements SmartClassLoad
|
||||
* @param urls the urls managed by the classloader
|
||||
* @param logger the logger used for messages
|
||||
*/
|
||||
public RestartClassLoader(ClassLoader parent, URL[] urls,
|
||||
ClassLoaderFileRepository updatedFiles, Log logger) {
|
||||
public RestartClassLoader(ClassLoader parent, URL[] urls, ClassLoaderFileRepository updatedFiles, Log logger) {
|
||||
super(urls, parent);
|
||||
Assert.notNull(parent, "Parent must not be null");
|
||||
Assert.notNull(updatedFiles, "UpdatedFiles must not be null");
|
||||
@@ -126,13 +124,11 @@ public class RestartClassLoader extends URLClassLoader implements SmartClassLoad
|
||||
if (file.getKind() == Kind.DELETED) {
|
||||
return null;
|
||||
}
|
||||
return AccessController
|
||||
.doPrivileged((PrivilegedAction<URL>) () -> createFileUrl(name, file));
|
||||
return AccessController.doPrivileged((PrivilegedAction<URL>) () -> createFileUrl(name, file));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> loadClass(String name, boolean resolve)
|
||||
throws ClassNotFoundException {
|
||||
public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||
String path = name.replace('.', '/').concat(".class");
|
||||
ClassLoaderFile file = this.updatedFiles.getFile(path);
|
||||
if (file != null && file.getKind() == Kind.DELETED) {
|
||||
@@ -173,8 +169,7 @@ public class RestartClassLoader extends URLClassLoader implements SmartClassLoad
|
||||
|
||||
private URL createFileUrl(String name, ClassLoaderFile file) {
|
||||
try {
|
||||
return new URL("reloaded", null, -1, "/" + name,
|
||||
new ClassLoaderFileURLStreamHandler(file));
|
||||
return new URL("reloaded", null, -1, "/" + name, new ClassLoaderFileURLStreamHandler(file));
|
||||
}
|
||||
catch (MalformedURLException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -38,12 +38,10 @@ public class DefaultSourceFolderUrlFilter implements SourceFolderUrlFilter {
|
||||
|
||||
private static final Pattern URL_MODULE_PATTERN = Pattern.compile(".*\\/(.+)\\.jar");
|
||||
|
||||
private static final Pattern VERSION_PATTERN = Pattern
|
||||
.compile("^-\\d+(?:\\.\\d+)*(?:[.-].+)?$");
|
||||
private static final Pattern VERSION_PATTERN = Pattern.compile("^-\\d+(?:\\.\\d+)*(?:[.-].+)?$");
|
||||
|
||||
private static final Set<String> SKIPPED_PROJECTS = new HashSet<>(Arrays.asList(
|
||||
"spring-boot", "spring-boot-devtools", "spring-boot-autoconfigure",
|
||||
"spring-boot-actuator", "spring-boot-starter"));
|
||||
private static final Set<String> SKIPPED_PROJECTS = new HashSet<>(Arrays.asList("spring-boot",
|
||||
"spring-boot-devtools", "spring-boot-autoconfigure", "spring-boot-actuator", "spring-boot-starter"));
|
||||
|
||||
@Override
|
||||
public boolean isMatch(String sourceFolder, URL url) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -67,12 +67,10 @@ public class HttpRestartServer {
|
||||
* @param response the response
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
public void handle(ServerHttpRequest request, ServerHttpResponse response)
|
||||
throws IOException {
|
||||
public void handle(ServerHttpRequest request, ServerHttpResponse response) throws IOException {
|
||||
try {
|
||||
Assert.state(request.getHeaders().getContentLength() > 0, "No content");
|
||||
ObjectInputStream objectInputStream = new ObjectInputStream(
|
||||
request.getBody());
|
||||
ObjectInputStream objectInputStream = new ObjectInputStream(request.getBody());
|
||||
ClassLoaderFiles files = (ClassLoaderFiles) objectInputStream.readObject();
|
||||
objectInputStream.close();
|
||||
this.server.updateAndRestart(files);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -43,8 +43,7 @@ public class HttpRestartServerHandler implements Handler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(ServerHttpRequest request, ServerHttpResponse response)
|
||||
throws IOException {
|
||||
public void handle(ServerHttpRequest request, ServerHttpResponse response) throws IOException {
|
||||
this.server.handle(request, response);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -67,8 +67,7 @@ public class RestartServer {
|
||||
* local classpath
|
||||
* @param classLoader the application classloader
|
||||
*/
|
||||
public RestartServer(SourceFolderUrlFilter sourceFolderUrlFilter,
|
||||
ClassLoader classLoader) {
|
||||
public RestartServer(SourceFolderUrlFilter sourceFolderUrlFilter, ClassLoader classLoader) {
|
||||
Assert.notNull(sourceFolderUrlFilter, "SourceFolderUrlFilter must not be null");
|
||||
Assert.notNull(classLoader, "ClassLoader must not be null");
|
||||
this.sourceFolderUrlFilter = sourceFolderUrlFilter;
|
||||
@@ -97,8 +96,7 @@ public class RestartServer {
|
||||
restart(urls, files);
|
||||
}
|
||||
|
||||
private boolean updateFileSystem(URL url, String name,
|
||||
ClassLoaderFile classLoaderFile) {
|
||||
private boolean updateFileSystem(URL url, String name, ClassLoaderFile classLoaderFile) {
|
||||
if (!isFolderUrl(url.toString())) {
|
||||
return false;
|
||||
}
|
||||
@@ -128,8 +126,7 @@ public class RestartServer {
|
||||
for (URL url : urls) {
|
||||
if (this.sourceFolderUrlFilter.isMatch(sourceFolder, url)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("URL " + url + " matched against source folder "
|
||||
+ sourceFolder);
|
||||
logger.debug("URL " + url + " matched against source folder " + sourceFolder);
|
||||
}
|
||||
matchingUrls.add(url);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -104,23 +104,19 @@ public class DevToolsSettings {
|
||||
static DevToolsSettings load(String location) {
|
||||
try {
|
||||
DevToolsSettings settings = new DevToolsSettings();
|
||||
Enumeration<URL> urls = Thread.currentThread().getContextClassLoader()
|
||||
.getResources(location);
|
||||
Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(location);
|
||||
while (urls.hasMoreElements()) {
|
||||
settings.add(PropertiesLoaderUtils
|
||||
.loadProperties(new UrlResource(urls.nextElement())));
|
||||
settings.add(PropertiesLoaderUtils.loadProperties(new UrlResource(urls.nextElement())));
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Included patterns for restart : "
|
||||
+ settings.restartIncludePatterns);
|
||||
logger.debug("Excluded patterns for restart : "
|
||||
+ settings.restartExcludePatterns);
|
||||
logger.debug("Included patterns for restart : " + settings.restartIncludePatterns);
|
||||
logger.debug("Excluded patterns for restart : " + settings.restartExcludePatterns);
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("Unable to load devtools settings from "
|
||||
+ "location [" + location + "]", ex);
|
||||
throw new IllegalStateException("Unable to load devtools settings from " + "location [" + location + "]",
|
||||
ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -77,8 +77,7 @@ public class HttpTunnelConnection implements TunnelConnection {
|
||||
* @param requestFactory the HTTP request factory
|
||||
* @param executor the executor used to handle connections
|
||||
*/
|
||||
protected HttpTunnelConnection(String url, ClientHttpRequestFactory requestFactory,
|
||||
Executor executor) {
|
||||
protected HttpTunnelConnection(String url, ClientHttpRequestFactory requestFactory, Executor executor) {
|
||||
Assert.hasLength(url, "URL must not be empty");
|
||||
Assert.notNull(requestFactory, "RequestFactory must not be null");
|
||||
try {
|
||||
@@ -88,19 +87,16 @@ public class HttpTunnelConnection implements TunnelConnection {
|
||||
throw new IllegalArgumentException("Malformed URL '" + url + "'");
|
||||
}
|
||||
this.requestFactory = requestFactory;
|
||||
this.executor = (executor != null) ? executor
|
||||
: Executors.newCachedThreadPool(new TunnelThreadFactory());
|
||||
this.executor = (executor != null) ? executor : Executors.newCachedThreadPool(new TunnelThreadFactory());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TunnelChannel open(WritableByteChannel incomingChannel, Closeable closeable)
|
||||
throws Exception {
|
||||
public TunnelChannel open(WritableByteChannel incomingChannel, Closeable closeable) throws Exception {
|
||||
logger.trace("Opening HTTP tunnel to " + this.uri);
|
||||
return new TunnelChannel(incomingChannel, closeable);
|
||||
}
|
||||
|
||||
protected final ClientHttpRequest createRequest(boolean hasPayload)
|
||||
throws IOException {
|
||||
protected final ClientHttpRequest createRequest(boolean hasPayload) throws IOException {
|
||||
HttpMethod method = hasPayload ? HttpMethod.POST : HttpMethod.GET;
|
||||
return this.requestFactory.createRequest(this.uri, method);
|
||||
}
|
||||
@@ -141,8 +137,7 @@ public class HttpTunnelConnection implements TunnelConnection {
|
||||
public int write(ByteBuffer src) throws IOException {
|
||||
int size = src.remaining();
|
||||
if (size > 0) {
|
||||
openNewConnection(
|
||||
new HttpTunnelPayload(this.requestSeq.incrementAndGet(), src));
|
||||
openNewConnection(new HttpTunnelPayload(this.requestSeq.incrementAndGet(), src));
|
||||
}
|
||||
return size;
|
||||
}
|
||||
@@ -157,8 +152,7 @@ public class HttpTunnelConnection implements TunnelConnection {
|
||||
}
|
||||
catch (IOException ex) {
|
||||
if (ex instanceof ConnectException) {
|
||||
logger.warn("Failed to connect to remote application at "
|
||||
+ HttpTunnelConnection.this.uri);
|
||||
logger.warn("Failed to connect to remote application at " + HttpTunnelConnection.this.uri);
|
||||
}
|
||||
else {
|
||||
logger.trace("Unexpected connection error", ex);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -144,8 +144,7 @@ public class TunnelClient implements SmartInitializingSingleton {
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
logger.trace("Closing tunnel client on port "
|
||||
+ this.serverSocketChannel.socket().getLocalPort());
|
||||
logger.trace("Closing tunnel client on port " + this.serverSocketChannel.socket().getLocalPort());
|
||||
this.serverSocketChannel.close();
|
||||
this.acceptConnections = false;
|
||||
interrupt();
|
||||
@@ -171,10 +170,10 @@ public class TunnelClient implements SmartInitializingSingleton {
|
||||
private void handleConnection(SocketChannel socketChannel) throws Exception {
|
||||
Closeable closeable = new SocketCloseable(socketChannel);
|
||||
TunnelClient.this.listeners.fireOpenEvent(socketChannel);
|
||||
try (WritableByteChannel outputChannel = TunnelClient.this.tunnelConnection
|
||||
.open(socketChannel, closeable)) {
|
||||
logger.trace("Accepted connection to tunnel client from "
|
||||
+ socketChannel.socket().getRemoteSocketAddress());
|
||||
try (WritableByteChannel outputChannel = TunnelClient.this.tunnelConnection.open(socketChannel,
|
||||
closeable)) {
|
||||
logger.trace(
|
||||
"Accepted connection to tunnel client from " + socketChannel.socket().getRemoteSocketAddress());
|
||||
while (true) {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
|
||||
int amountRead = socketChannel.read(buffer);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -37,7 +37,6 @@ public interface TunnelConnection {
|
||||
* destined for the remote server
|
||||
* @throws Exception in case of errors
|
||||
*/
|
||||
WritableByteChannel open(WritableByteChannel incomingChannel, Closeable closeable)
|
||||
throws Exception;
|
||||
WritableByteChannel open(WritableByteChannel incomingChannel, Closeable closeable) throws Exception;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -134,8 +134,7 @@ public class HttpTunnelPayload {
|
||||
* @return payload data or {@code null}
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
public static ByteBuffer getPayloadData(ReadableByteChannel channel)
|
||||
throws IOException {
|
||||
public static ByteBuffer getPayloadData(ReadableByteChannel channel) throws IOException {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
|
||||
try {
|
||||
int amountRead = channel.read(buffer);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -55,8 +55,7 @@ public class HttpTunnelPayloadForwarder {
|
||||
synchronized (this.monitor) {
|
||||
long seq = payload.getSequence();
|
||||
if (this.lastRequestSeq != seq - 1) {
|
||||
Assert.state(this.queue.size() < MAXIMUM_QUEUE_SIZE,
|
||||
"Too many messages queued");
|
||||
Assert.state(this.queue.size() < MAXIMUM_QUEUE_SIZE, "Too many messages queued");
|
||||
this.queue.put(seq, payload);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -112,8 +112,7 @@ public class HttpTunnelServer {
|
||||
|
||||
private static final long DEFAULT_DISCONNECT_TIMEOUT = TimeUnit.SECONDS.toMillis(30);
|
||||
|
||||
private static final MediaType DISCONNECT_MEDIA_TYPE = new MediaType("application",
|
||||
"x-disconnect");
|
||||
private static final MediaType DISCONNECT_MEDIA_TYPE = new MediaType("application", "x-disconnect");
|
||||
|
||||
private static final Log logger = LogFactory.getLog(HttpTunnelServer.class);
|
||||
|
||||
@@ -140,8 +139,7 @@ public class HttpTunnelServer {
|
||||
* @param response the HTTP response
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
public void handle(ServerHttpRequest request, ServerHttpResponse response)
|
||||
throws IOException {
|
||||
public void handle(ServerHttpRequest request, ServerHttpResponse response) throws IOException {
|
||||
handle(new HttpConnection(request, response));
|
||||
}
|
||||
|
||||
@@ -199,8 +197,7 @@ public class HttpTunnelServer {
|
||||
* @param disconnectTimeout the disconnect timeout in milliseconds
|
||||
*/
|
||||
public void setDisconnectTimeout(long disconnectTimeout) {
|
||||
Assert.isTrue(disconnectTimeout > 0,
|
||||
"DisconnectTimeout must be a positive value");
|
||||
Assert.isTrue(disconnectTimeout > 0, "DisconnectTimeout must be a positive value");
|
||||
this.disconnectTimeout = disconnectTimeout;
|
||||
}
|
||||
|
||||
@@ -252,8 +249,7 @@ public class HttpTunnelServer {
|
||||
ByteBuffer data = HttpTunnelPayload.getPayloadData(this.targetServer);
|
||||
synchronized (this.httpConnections) {
|
||||
if (data != null) {
|
||||
HttpTunnelPayload payload = new HttpTunnelPayload(
|
||||
this.responseSeq.incrementAndGet(), data);
|
||||
HttpTunnelPayload payload = new HttpTunnelPayload(this.responseSeq.incrementAndGet(), data);
|
||||
payload.logIncoming();
|
||||
HttpConnection connection = getOrWaitForHttpConnection();
|
||||
connection.respond(payload);
|
||||
@@ -285,8 +281,7 @@ public class HttpTunnelServer {
|
||||
Iterator<HttpConnection> iterator = this.httpConnections.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
HttpConnection httpConnection = iterator.next();
|
||||
if (httpConnection
|
||||
.isOlderThan(HttpTunnelServer.this.longPollTimeout)) {
|
||||
if (httpConnection.isOlderThan(HttpTunnelServer.this.longPollTimeout)) {
|
||||
httpConnection.respond(HttpStatus.NO_CONTENT);
|
||||
iterator.remove();
|
||||
}
|
||||
@@ -298,8 +293,7 @@ public class HttpTunnelServer {
|
||||
if (this.lastHttpRequestTime > 0) {
|
||||
long timeout = HttpTunnelServer.this.disconnectTimeout;
|
||||
long duration = System.currentTimeMillis() - this.lastHttpRequestTime;
|
||||
Assert.state(duration < timeout,
|
||||
() -> "Disconnect timeout: " + timeout + " " + duration);
|
||||
Assert.state(duration < timeout, () -> "Disconnect timeout: " + timeout + " " + duration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,8 +330,7 @@ public class HttpTunnelServer {
|
||||
}
|
||||
synchronized (this.httpConnections) {
|
||||
while (this.httpConnections.size() > 1) {
|
||||
this.httpConnections.removeFirst()
|
||||
.respond(HttpStatus.TOO_MANY_REQUESTS);
|
||||
this.httpConnections.removeFirst().respond(HttpStatus.TOO_MANY_REQUESTS);
|
||||
}
|
||||
this.lastHttpRequestTime = System.currentTimeMillis();
|
||||
this.httpConnections.addLast(httpConnection);
|
||||
@@ -346,8 +339,7 @@ public class HttpTunnelServer {
|
||||
forwardToTargetServer(httpConnection);
|
||||
}
|
||||
|
||||
private void forwardToTargetServer(HttpConnection httpConnection)
|
||||
throws IOException {
|
||||
private void forwardToTargetServer(HttpConnection httpConnection) throws IOException {
|
||||
if (httpConnection.isDisconnectRequest()) {
|
||||
this.targetServer.close();
|
||||
interrupt();
|
||||
@@ -391,8 +383,7 @@ public class HttpTunnelServer {
|
||||
protected ServerHttpAsyncRequestControl startAsync() {
|
||||
try {
|
||||
// Try to use async to save blocking
|
||||
ServerHttpAsyncRequestControl async = this.request
|
||||
.getAsyncRequestControl(this.response);
|
||||
ServerHttpAsyncRequestControl async = this.request.getAsyncRequestControl(this.response);
|
||||
async.start();
|
||||
return async;
|
||||
}
|
||||
@@ -451,8 +442,7 @@ public class HttpTunnelServer {
|
||||
* @return if the request is a signal to disconnect
|
||||
*/
|
||||
public boolean isDisconnectRequest() {
|
||||
return DISCONNECT_MEDIA_TYPE
|
||||
.equals(this.request.getHeaders().getContentType());
|
||||
return DISCONNECT_MEDIA_TYPE.equals(this.request.getHeaders().getContentType());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -43,8 +43,7 @@ public class HttpTunnelServerHandler implements Handler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(ServerHttpRequest request, ServerHttpResponse response)
|
||||
throws IOException {
|
||||
public void handle(ServerHttpRequest request, ServerHttpResponse response) throws IOException {
|
||||
this.server.handle(request, response);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -38,8 +38,7 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class SocketTargetServerConnection implements TargetServerConnection {
|
||||
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(SocketTargetServerConnection.class);
|
||||
private static final Log logger = LogFactory.getLog(SocketTargetServerConnection.class);
|
||||
|
||||
private final PortProvider portProvider;
|
||||
|
||||
@@ -73,8 +72,7 @@ public class SocketTargetServerConnection implements TargetServerConnection {
|
||||
|
||||
TimeoutAwareChannel(SocketChannel socketChannel) throws IOException {
|
||||
this.socketChannel = socketChannel;
|
||||
this.readChannel = Channels
|
||||
.newChannel(socketChannel.socket().getInputStream());
|
||||
this.readChannel = Channels.newChannel(socketChannel.socket().getInputStream());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -38,14 +38,13 @@ public class RemoteUrlPropertyExtractorTests {
|
||||
|
||||
@After
|
||||
public void preventRunFailuresFromPollutingLoggerContext() {
|
||||
((Logger) LoggerFactory.getLogger(RemoteUrlPropertyExtractorTests.class))
|
||||
.getLoggerContext().getTurboFilterList().clear();
|
||||
((Logger) LoggerFactory.getLogger(RemoteUrlPropertyExtractorTests.class)).getLoggerContext()
|
||||
.getTurboFilterList().clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingUrl() {
|
||||
assertThatIllegalStateException().isThrownBy(() -> doTest())
|
||||
.withMessageContaining("No remote URL specified");
|
||||
assertThatIllegalStateException().isThrownBy(() -> doTest()).withMessageContaining("No remote URL specified");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -57,26 +56,21 @@ public class RemoteUrlPropertyExtractorTests {
|
||||
|
||||
@Test
|
||||
public void multipleUrls() {
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(
|
||||
() -> doTest("http://localhost:8080", "http://localhost:9090"))
|
||||
assertThatIllegalStateException().isThrownBy(() -> doTest("http://localhost:8080", "http://localhost:9090"))
|
||||
.withMessageContaining("Multiple URLs specified");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validUrl() {
|
||||
ApplicationContext context = doTest("http://localhost:8080");
|
||||
assertThat(context.getEnvironment().getProperty("remoteUrl"))
|
||||
.isEqualTo("http://localhost:8080");
|
||||
assertThat(context.getEnvironment().getProperty("spring.thymeleaf.cache"))
|
||||
.isNull();
|
||||
assertThat(context.getEnvironment().getProperty("remoteUrl")).isEqualTo("http://localhost:8080");
|
||||
assertThat(context.getEnvironment().getProperty("spring.thymeleaf.cache")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cleanValidUrl() {
|
||||
ApplicationContext context = doTest("http://localhost:8080/");
|
||||
assertThat(context.getEnvironment().getProperty("remoteUrl"))
|
||||
.isEqualTo("http://localhost:8080");
|
||||
assertThat(context.getEnvironment().getProperty("remoteUrl")).isEqualTo("http://localhost:8080");
|
||||
}
|
||||
|
||||
private ApplicationContext doTest(String... args) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -50,8 +50,7 @@ public abstract class AbstractDevToolsDataSourceAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void singleManuallyConfiguredDataSourceIsNotClosed() throws SQLException {
|
||||
ConfigurableApplicationContext context = createContext(
|
||||
SingleDataSourceConfiguration.class);
|
||||
ConfigurableApplicationContext context = createContext(SingleDataSourceConfiguration.class);
|
||||
DataSource dataSource = context.getBean(DataSource.class);
|
||||
Statement statement = configureDataSourceBehavior(dataSource);
|
||||
verify(statement, never()).execute("SHUTDOWN");
|
||||
@@ -59,10 +58,8 @@ public abstract class AbstractDevToolsDataSourceAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void multipleDataSourcesAreIgnored() throws SQLException {
|
||||
ConfigurableApplicationContext context = createContext(
|
||||
MultipleDataSourcesConfiguration.class);
|
||||
Collection<DataSource> dataSources = context.getBeansOfType(DataSource.class)
|
||||
.values();
|
||||
ConfigurableApplicationContext context = createContext(MultipleDataSourcesConfiguration.class);
|
||||
Collection<DataSource> dataSources = context.getBeansOfType(DataSource.class).values();
|
||||
for (DataSource dataSource : dataSources) {
|
||||
Statement statement = configureDataSourceBehavior(dataSource);
|
||||
verify(statement, never()).execute("SHUTDOWN");
|
||||
@@ -73,16 +70,14 @@ public abstract class AbstractDevToolsDataSourceAutoConfigurationTests {
|
||||
public void emptyFactoryMethodMetadataIgnored() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
DataSource dataSource = mock(DataSource.class);
|
||||
AnnotatedGenericBeanDefinition beanDefinition = new AnnotatedGenericBeanDefinition(
|
||||
dataSource.getClass());
|
||||
AnnotatedGenericBeanDefinition beanDefinition = new AnnotatedGenericBeanDefinition(dataSource.getClass());
|
||||
context.registerBeanDefinition("dataSource", beanDefinition);
|
||||
context.register(DevToolsDataSourceAutoConfiguration.class);
|
||||
context.refresh();
|
||||
context.close();
|
||||
}
|
||||
|
||||
protected final Statement configureDataSourceBehavior(DataSource dataSource)
|
||||
throws SQLException {
|
||||
protected final Statement configureDataSourceBehavior(DataSource dataSource) throws SQLException {
|
||||
Connection connection = mock(Connection.class);
|
||||
Statement statement = mock(Statement.class);
|
||||
doReturn(connection).when(dataSource).getConnection();
|
||||
@@ -94,20 +89,17 @@ public abstract class AbstractDevToolsDataSourceAutoConfigurationTests {
|
||||
return this.createContext(null, classes);
|
||||
}
|
||||
|
||||
protected final ConfigurableApplicationContext createContext(String driverClassName,
|
||||
Class<?>... classes) {
|
||||
protected final ConfigurableApplicationContext createContext(String driverClassName, Class<?>... classes) {
|
||||
return this.createContext(driverClassName, null, classes);
|
||||
}
|
||||
|
||||
protected final ConfigurableApplicationContext createContext(String driverClassName,
|
||||
String url, Class<?>... classes) {
|
||||
protected final ConfigurableApplicationContext createContext(String driverClassName, String url,
|
||||
Class<?>... classes) {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.register(classes);
|
||||
context.register(DevToolsDataSourceAutoConfiguration.class);
|
||||
if (driverClassName != null) {
|
||||
TestPropertyValues
|
||||
.of("spring.datasource.driver-class-name:" + driverClassName)
|
||||
.applyTo(context);
|
||||
TestPropertyValues.of("spring.datasource.driver-class-name:" + driverClassName).applyTo(context);
|
||||
}
|
||||
if (url != null) {
|
||||
TestPropertyValues.of("spring.datasource.url:" + url).applyTo(context);
|
||||
@@ -154,8 +146,7 @@ public abstract class AbstractDevToolsDataSourceAutoConfigurationTests {
|
||||
private static class DataSourceSpyBeanPostProcessor implements BeanPostProcessor {
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (bean instanceof DataSource) {
|
||||
bean = spy(bean);
|
||||
}
|
||||
@@ -163,8 +154,7 @@ public abstract class AbstractDevToolsDataSourceAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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,15 +39,13 @@ import static org.mockito.Mockito.verify;
|
||||
*/
|
||||
@RunWith(ModifiedClassPathRunner.class)
|
||||
@ClassPathExclusions("HikariCP-*.jar")
|
||||
public class DevToolsEmbeddedDataSourceAutoConfigurationTests
|
||||
extends AbstractDevToolsDataSourceAutoConfigurationTests {
|
||||
public class DevToolsEmbeddedDataSourceAutoConfigurationTests extends AbstractDevToolsDataSourceAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void autoConfiguredDataSourceIsNotShutdown() throws SQLException {
|
||||
ConfigurableApplicationContext context = createContext(
|
||||
DataSourceAutoConfiguration.class, DataSourceSpyConfiguration.class);
|
||||
Statement statement = configureDataSourceBehavior(
|
||||
context.getBean(DataSource.class));
|
||||
ConfigurableApplicationContext context = createContext(DataSourceAutoConfiguration.class,
|
||||
DataSourceSpyConfiguration.class);
|
||||
Statement statement = configureDataSourceBehavior(context.getBean(DataSource.class));
|
||||
context.close();
|
||||
verify(statement, never()).execute("SHUTDOWN");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -37,8 +37,7 @@ import static org.mockito.Mockito.verify;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class DevToolsPooledDataSourceAutoConfigurationTests
|
||||
extends AbstractDevToolsDataSourceAutoConfigurationTests {
|
||||
public class DevToolsPooledDataSourceAutoConfigurationTests extends AbstractDevToolsDataSourceAutoConfigurationTests {
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
@@ -52,10 +51,9 @@ public class DevToolsPooledDataSourceAutoConfigurationTests
|
||||
|
||||
@Test
|
||||
public void autoConfiguredInMemoryDataSourceIsShutdown() throws SQLException {
|
||||
ConfigurableApplicationContext context = createContext(
|
||||
DataSourceAutoConfiguration.class, DataSourceSpyConfiguration.class);
|
||||
Statement statement = configureDataSourceBehavior(
|
||||
context.getBean(DataSource.class));
|
||||
ConfigurableApplicationContext context = createContext(DataSourceAutoConfiguration.class,
|
||||
DataSourceSpyConfiguration.class);
|
||||
Statement statement = configureDataSourceBehavior(context.getBean(DataSource.class));
|
||||
context.close();
|
||||
verify(statement).execute("SHUTDOWN");
|
||||
}
|
||||
@@ -64,74 +62,61 @@ public class DevToolsPooledDataSourceAutoConfigurationTests
|
||||
public void autoConfiguredExternalDataSourceIsNotShutdown() throws SQLException {
|
||||
ConfigurableApplicationContext context = createContext("org.postgresql.Driver",
|
||||
DataSourceAutoConfiguration.class, DataSourceSpyConfiguration.class);
|
||||
Statement statement = configureDataSourceBehavior(
|
||||
context.getBean(DataSource.class));
|
||||
Statement statement = configureDataSourceBehavior(context.getBean(DataSource.class));
|
||||
context.close();
|
||||
verify(statement, never()).execute("SHUTDOWN");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void h2ServerIsNotShutdown() throws SQLException {
|
||||
ConfigurableApplicationContext context = createContext("org.h2.Driver",
|
||||
"jdbc:h2:hsql://localhost", DataSourceAutoConfiguration.class,
|
||||
DataSourceSpyConfiguration.class);
|
||||
Statement statement = configureDataSourceBehavior(
|
||||
context.getBean(DataSource.class));
|
||||
ConfigurableApplicationContext context = createContext("org.h2.Driver", "jdbc:h2:hsql://localhost",
|
||||
DataSourceAutoConfiguration.class, DataSourceSpyConfiguration.class);
|
||||
Statement statement = configureDataSourceBehavior(context.getBean(DataSource.class));
|
||||
context.close();
|
||||
verify(statement, never()).execute("SHUTDOWN");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inMemoryH2IsShutdown() throws SQLException {
|
||||
ConfigurableApplicationContext context = createContext("org.h2.Driver",
|
||||
"jdbc:h2:mem:test", DataSourceAutoConfiguration.class,
|
||||
DataSourceSpyConfiguration.class);
|
||||
Statement statement = configureDataSourceBehavior(
|
||||
context.getBean(DataSource.class));
|
||||
ConfigurableApplicationContext context = createContext("org.h2.Driver", "jdbc:h2:mem:test",
|
||||
DataSourceAutoConfiguration.class, DataSourceSpyConfiguration.class);
|
||||
Statement statement = configureDataSourceBehavior(context.getBean(DataSource.class));
|
||||
context.close();
|
||||
verify(statement, times(1)).execute("SHUTDOWN");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hsqlServerIsNotShutdown() throws SQLException {
|
||||
ConfigurableApplicationContext context = createContext("org.hsqldb.jdbcDriver",
|
||||
"jdbc:hsqldb:hsql://localhost", DataSourceAutoConfiguration.class,
|
||||
DataSourceSpyConfiguration.class);
|
||||
Statement statement = configureDataSourceBehavior(
|
||||
context.getBean(DataSource.class));
|
||||
ConfigurableApplicationContext context = createContext("org.hsqldb.jdbcDriver", "jdbc:hsqldb:hsql://localhost",
|
||||
DataSourceAutoConfiguration.class, DataSourceSpyConfiguration.class);
|
||||
Statement statement = configureDataSourceBehavior(context.getBean(DataSource.class));
|
||||
context.close();
|
||||
verify(statement, never()).execute("SHUTDOWN");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inMemoryHsqlIsShutdown() throws SQLException {
|
||||
ConfigurableApplicationContext context = createContext("org.hsqldb.jdbcDriver",
|
||||
"jdbc:hsqldb:mem:test", DataSourceAutoConfiguration.class,
|
||||
DataSourceSpyConfiguration.class);
|
||||
Statement statement = configureDataSourceBehavior(
|
||||
context.getBean(DataSource.class));
|
||||
ConfigurableApplicationContext context = createContext("org.hsqldb.jdbcDriver", "jdbc:hsqldb:mem:test",
|
||||
DataSourceAutoConfiguration.class, DataSourceSpyConfiguration.class);
|
||||
Statement statement = configureDataSourceBehavior(context.getBean(DataSource.class));
|
||||
context.close();
|
||||
verify(statement, times(1)).execute("SHUTDOWN");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void derbyClientIsNotShutdown() throws SQLException {
|
||||
ConfigurableApplicationContext context = createContext(
|
||||
"org.apache.derby.jdbc.ClientDriver", "jdbc:derby://localhost",
|
||||
DataSourceAutoConfiguration.class, DataSourceSpyConfiguration.class);
|
||||
Statement statement = configureDataSourceBehavior(
|
||||
context.getBean(DataSource.class));
|
||||
ConfigurableApplicationContext context = createContext("org.apache.derby.jdbc.ClientDriver",
|
||||
"jdbc:derby://localhost", DataSourceAutoConfiguration.class, DataSourceSpyConfiguration.class);
|
||||
Statement statement = configureDataSourceBehavior(context.getBean(DataSource.class));
|
||||
context.close();
|
||||
verify(statement, never()).execute("SHUTDOWN");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inMemoryDerbyIsShutdown() throws SQLException {
|
||||
ConfigurableApplicationContext context = createContext(
|
||||
"org.apache.derby.jdbc.EmbeddedDriver", "jdbc:derby:memory:test",
|
||||
DataSourceAutoConfiguration.class, DataSourceSpyConfiguration.class);
|
||||
Statement statement = configureDataSourceBehavior(
|
||||
context.getBean(DataSource.class));
|
||||
ConfigurableApplicationContext context = createContext("org.apache.derby.jdbc.EmbeddedDriver",
|
||||
"jdbc:derby:memory:test", DataSourceAutoConfiguration.class, DataSourceSpyConfiguration.class);
|
||||
Statement statement = configureDataSourceBehavior(context.getBean(DataSource.class));
|
||||
context.close();
|
||||
verify(statement, times(1)).execute("SHUTDOWN");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -33,9 +33,8 @@ public class DevToolsPropertiesTests {
|
||||
public void additionalExcludeKeepsDefaults() {
|
||||
DevToolsProperties.Restart restart = this.devToolsProperties.getRestart();
|
||||
restart.setAdditionalExclude("foo/**,bar/**");
|
||||
assertThat(restart.getAllExclude()).containsOnly("META-INF/maven/**",
|
||||
"META-INF/resources/**", "resources/**", "static/**", "public/**",
|
||||
"templates/**", "**/*Test.class", "**/*Tests.class", "git.properties",
|
||||
assertThat(restart.getAllExclude()).containsOnly("META-INF/maven/**", "META-INF/resources/**", "resources/**",
|
||||
"static/**", "public/**", "templates/**", "**/*Test.class", "**/*Tests.class", "git.properties",
|
||||
"META-INF/build-info.properties", "foo/**", "bar/**");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -41,12 +41,9 @@ public class HateoasObjenesisCacheDisablerTests {
|
||||
@Before
|
||||
@After
|
||||
public void resetCacheField() {
|
||||
ReflectionTestUtils.setField(HateoasObjenesisCacheDisabler.class, "cacheDisabled",
|
||||
false);
|
||||
this.objenesis = (ObjenesisStd) ReflectionTestUtils
|
||||
.getField(DummyInvocationUtils.class, "OBJENESIS");
|
||||
ReflectionTestUtils.setField(this.objenesis, "cache",
|
||||
new ConcurrentHashMap<String, ObjectInstantiator<?>>());
|
||||
ReflectionTestUtils.setField(HateoasObjenesisCacheDisabler.class, "cacheDisabled", false);
|
||||
this.objenesis = (ObjenesisStd) ReflectionTestUtils.getField(DummyInvocationUtils.class, "OBJENESIS");
|
||||
ReflectionTestUtils.setField(this.objenesis, "cache", new ConcurrentHashMap<String, ObjectInstantiator<?>>());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -86,28 +86,24 @@ public class LocalDevToolsAutoConfigurationTests {
|
||||
@Test
|
||||
public void thymeleafCacheIsFalse() {
|
||||
this.context = initializeAndRun(Config.class);
|
||||
SpringResourceTemplateResolver resolver = this.context
|
||||
.getBean(SpringResourceTemplateResolver.class);
|
||||
SpringResourceTemplateResolver resolver = this.context.getBean(SpringResourceTemplateResolver.class);
|
||||
assertThat(resolver.isCacheable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultPropertyCanBeOverriddenFromCommandLine() {
|
||||
this.context = initializeAndRun(Config.class, "--spring.thymeleaf.cache=true");
|
||||
SpringResourceTemplateResolver resolver = this.context
|
||||
.getBean(SpringResourceTemplateResolver.class);
|
||||
SpringResourceTemplateResolver resolver = this.context.getBean(SpringResourceTemplateResolver.class);
|
||||
assertThat(resolver.isCacheable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultPropertyCanBeOverriddenFromUserHomeProperties() {
|
||||
String userHome = System.getProperty("user.home");
|
||||
System.setProperty("user.home",
|
||||
new File("src/test/resources/user-home").getAbsolutePath());
|
||||
System.setProperty("user.home", new File("src/test/resources/user-home").getAbsolutePath());
|
||||
try {
|
||||
this.context = initializeAndRun(Config.class);
|
||||
SpringResourceTemplateResolver resolver = this.context
|
||||
.getBean(SpringResourceTemplateResolver.class);
|
||||
SpringResourceTemplateResolver resolver = this.context.getBean(SpringResourceTemplateResolver.class);
|
||||
assertThat(resolver.isCacheable()).isTrue();
|
||||
}
|
||||
finally {
|
||||
@@ -143,8 +139,7 @@ public class LocalDevToolsAutoConfigurationTests {
|
||||
this.context = initializeAndRun(ConfigWithMockLiveReload.class);
|
||||
LiveReloadServer server = this.context.getBean(LiveReloadServer.class);
|
||||
reset(server);
|
||||
ClassPathChangedEvent event = new ClassPathChangedEvent(this.context,
|
||||
Collections.emptySet(), false);
|
||||
ClassPathChangedEvent event = new ClassPathChangedEvent(this.context, Collections.emptySet(), false);
|
||||
this.context.publishEvent(event);
|
||||
verify(server).triggerReload();
|
||||
}
|
||||
@@ -154,8 +149,7 @@ public class LocalDevToolsAutoConfigurationTests {
|
||||
this.context = initializeAndRun(ConfigWithMockLiveReload.class);
|
||||
LiveReloadServer server = this.context.getBean(LiveReloadServer.class);
|
||||
reset(server);
|
||||
ClassPathChangedEvent event = new ClassPathChangedEvent(this.context,
|
||||
Collections.emptySet(), true);
|
||||
ClassPathChangedEvent event = new ClassPathChangedEvent(this.context, Collections.emptySet(), true);
|
||||
this.context.publishEvent(event);
|
||||
verify(server, never()).triggerReload();
|
||||
}
|
||||
@@ -172,8 +166,7 @@ public class LocalDevToolsAutoConfigurationTests {
|
||||
@Test
|
||||
public void restartTriggeredOnClassPathChangeWithRestart() {
|
||||
this.context = initializeAndRun(Config.class);
|
||||
ClassPathChangedEvent event = new ClassPathChangedEvent(this.context,
|
||||
Collections.emptySet(), true);
|
||||
ClassPathChangedEvent event = new ClassPathChangedEvent(this.context, Collections.emptySet(), true);
|
||||
this.context.publishEvent(event);
|
||||
verify(this.mockRestarter.getMock()).restart(any(FailureHandler.class));
|
||||
}
|
||||
@@ -181,8 +174,7 @@ public class LocalDevToolsAutoConfigurationTests {
|
||||
@Test
|
||||
public void restartNotTriggeredOnClassPathChangeWithRestart() {
|
||||
this.context = initializeAndRun(Config.class);
|
||||
ClassPathChangedEvent event = new ClassPathChangedEvent(this.context,
|
||||
Collections.emptySet(), false);
|
||||
ClassPathChangedEvent event = new ClassPathChangedEvent(this.context, Collections.emptySet(), false);
|
||||
this.context.publishEvent(event);
|
||||
verify(this.mockRestarter.getMock(), never()).restart();
|
||||
}
|
||||
@@ -190,8 +182,7 @@ public class LocalDevToolsAutoConfigurationTests {
|
||||
@Test
|
||||
public void restartWatchingClassPath() {
|
||||
this.context = initializeAndRun(Config.class);
|
||||
ClassPathFileSystemWatcher watcher = this.context
|
||||
.getBean(ClassPathFileSystemWatcher.class);
|
||||
ClassPathFileSystemWatcher watcher = this.context.getBean(ClassPathFileSystemWatcher.class);
|
||||
assertThat(watcher).isNotNull();
|
||||
}
|
||||
|
||||
@@ -209,10 +200,8 @@ public class LocalDevToolsAutoConfigurationTests {
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put("spring.devtools.restart.trigger-file", "somefile.txt");
|
||||
this.context = initializeAndRun(Config.class, properties);
|
||||
ClassPathFileSystemWatcher classPathWatcher = this.context
|
||||
.getBean(ClassPathFileSystemWatcher.class);
|
||||
Object watcher = ReflectionTestUtils.getField(classPathWatcher,
|
||||
"fileSystemWatcher");
|
||||
ClassPathFileSystemWatcher classPathWatcher = this.context.getBean(ClassPathFileSystemWatcher.class);
|
||||
Object watcher = ReflectionTestUtils.getField(classPathWatcher, "fileSystemWatcher");
|
||||
Object filter = ReflectionTestUtils.getField(watcher, "triggerFilter");
|
||||
assertThat(filter).isInstanceOf(TriggerFileFilter.class);
|
||||
}
|
||||
@@ -220,18 +209,13 @@ public class LocalDevToolsAutoConfigurationTests {
|
||||
@Test
|
||||
public void watchingAdditionalPaths() {
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put("spring.devtools.restart.additional-paths",
|
||||
"src/main/java,src/test/java");
|
||||
properties.put("spring.devtools.restart.additional-paths", "src/main/java,src/test/java");
|
||||
this.context = initializeAndRun(Config.class, properties);
|
||||
ClassPathFileSystemWatcher classPathWatcher = this.context
|
||||
.getBean(ClassPathFileSystemWatcher.class);
|
||||
Object watcher = ReflectionTestUtils.getField(classPathWatcher,
|
||||
"fileSystemWatcher");
|
||||
ClassPathFileSystemWatcher classPathWatcher = this.context.getBean(ClassPathFileSystemWatcher.class);
|
||||
Object watcher = ReflectionTestUtils.getField(classPathWatcher, "fileSystemWatcher");
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<File, Object> folders = (Map<File, Object>) ReflectionTestUtils
|
||||
.getField(watcher, "folders");
|
||||
assertThat(folders).hasSize(2)
|
||||
.containsKey(new File("src/main/java").getAbsoluteFile())
|
||||
Map<File, Object> folders = (Map<File, Object>) ReflectionTestUtils.getField(watcher, "folders");
|
||||
assertThat(folders).hasSize(2).containsKey(new File("src/main/java").getAbsoluteFile())
|
||||
.containsKey(new File("src/test/java").getAbsoluteFile());
|
||||
}
|
||||
|
||||
@@ -247,13 +231,12 @@ public class LocalDevToolsAutoConfigurationTests {
|
||||
assertThat(options.getDevelopment()).isTrue();
|
||||
}
|
||||
|
||||
private ConfigurableApplicationContext initializeAndRun(Class<?> config,
|
||||
String... args) {
|
||||
private ConfigurableApplicationContext initializeAndRun(Class<?> config, String... args) {
|
||||
return initializeAndRun(config, Collections.emptyMap(), args);
|
||||
}
|
||||
|
||||
private ConfigurableApplicationContext initializeAndRun(Class<?> config,
|
||||
Map<String, Object> properties, String... args) {
|
||||
private ConfigurableApplicationContext initializeAndRun(Class<?> config, Map<String, Object> properties,
|
||||
String... args) {
|
||||
Restarter.initialize(new String[0], false, new MockRestartInitializer(), false);
|
||||
SpringApplication application = new SpringApplication(config);
|
||||
application.setDefaultProperties(getDefaultProperties(properties));
|
||||
@@ -261,8 +244,7 @@ public class LocalDevToolsAutoConfigurationTests {
|
||||
return context;
|
||||
}
|
||||
|
||||
private Map<String, Object> getDefaultProperties(
|
||||
Map<String, Object> specifiedProperties) {
|
||||
private Map<String, Object> getDefaultProperties(Map<String, Object> specifiedProperties) {
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put("spring.thymeleaf.check-template-location", false);
|
||||
properties.put("spring.devtools.livereload.port", 0);
|
||||
@@ -272,15 +254,15 @@ public class LocalDevToolsAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import({ ServletWebServerFactoryAutoConfiguration.class,
|
||||
LocalDevToolsAutoConfiguration.class, ThymeleafAutoConfiguration.class })
|
||||
@Import({ ServletWebServerFactoryAutoConfiguration.class, LocalDevToolsAutoConfiguration.class,
|
||||
ThymeleafAutoConfiguration.class })
|
||||
public static class Config {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ImportAutoConfiguration({ ServletWebServerFactoryAutoConfiguration.class,
|
||||
LocalDevToolsAutoConfiguration.class, ThymeleafAutoConfiguration.class })
|
||||
@ImportAutoConfiguration({ ServletWebServerFactoryAutoConfiguration.class, LocalDevToolsAutoConfiguration.class,
|
||||
ThymeleafAutoConfiguration.class })
|
||||
public static class ConfigWithMockLiveReload {
|
||||
|
||||
@Bean
|
||||
@@ -291,8 +273,8 @@ public class LocalDevToolsAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import({ ServletWebServerFactoryAutoConfiguration.class,
|
||||
LocalDevToolsAutoConfiguration.class, ResourceProperties.class })
|
||||
@Import({ ServletWebServerFactoryAutoConfiguration.class, LocalDevToolsAutoConfiguration.class,
|
||||
ResourceProperties.class })
|
||||
public static class WebResourcesConfig {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -128,8 +128,7 @@ public class RemoteDevToolsAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void invokeRestartWithCustomServerContextPath() throws Exception {
|
||||
loadContext("spring.devtools.remote.secret:supersecret",
|
||||
"server.servlet.context-path:/test");
|
||||
loadContext("spring.devtools.remote.secret:supersecret", "server.servlet.context-path:/test");
|
||||
DispatcherFilter filter = this.context.getBean(DispatcherFilter.class);
|
||||
this.request.setRequestURI("/test" + DEFAULT_CONTEXT_PATH + "/restart");
|
||||
this.request.addHeader(DEFAULT_SECRET_HEADER_NAME, "supersecret");
|
||||
@@ -139,8 +138,7 @@ public class RemoteDevToolsAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void disableRestart() {
|
||||
loadContext("spring.devtools.remote.secret:supersecret",
|
||||
"spring.devtools.remote.restart.enabled:false");
|
||||
loadContext("spring.devtools.remote.secret:supersecret", "spring.devtools.remote.restart.enabled:false");
|
||||
assertThatExceptionOfType(NoSuchBeanDefinitionException.class)
|
||||
.isThrownBy(() -> this.context.getBean("remoteRestartHandlerMapper"));
|
||||
}
|
||||
@@ -158,8 +156,7 @@ public class RemoteDevToolsAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void devToolsHealthWithCustomServerContextPathReturns200() throws Exception {
|
||||
loadContext("spring.devtools.remote.secret:supersecret",
|
||||
"server.servlet.context-path:/test");
|
||||
loadContext("spring.devtools.remote.secret:supersecret", "server.servlet.context-path:/test");
|
||||
DispatcherFilter filter = this.context.getBean(DispatcherFilter.class);
|
||||
this.request.setRequestURI("/test" + DEFAULT_CONTEXT_PATH);
|
||||
this.request.addHeader(DEFAULT_SECRET_HEADER_NAME, "supersecret");
|
||||
@@ -169,8 +166,7 @@ public class RemoteDevToolsAutoConfigurationTests {
|
||||
}
|
||||
|
||||
private void assertRestartInvoked(boolean value) {
|
||||
assertThat(this.context.getBean(MockHttpRestartServer.class).invoked)
|
||||
.isEqualTo(value);
|
||||
assertThat(this.context.getBean(MockHttpRestartServer.class).invoked).isEqualTo(value);
|
||||
}
|
||||
|
||||
private void loadContext(String... properties) {
|
||||
@@ -187,8 +183,7 @@ public class RemoteDevToolsAutoConfigurationTests {
|
||||
|
||||
@Bean
|
||||
public HttpRestartServer remoteRestartHttpRestartServer() {
|
||||
SourceFolderUrlFilter sourceFolderUrlFilter = mock(
|
||||
SourceFolderUrlFilter.class);
|
||||
SourceFolderUrlFilter sourceFolderUrlFilter = mock(SourceFolderUrlFilter.class);
|
||||
return new MockHttpRestartServer(sourceFolderUrlFilter);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -37,16 +37,14 @@ public class ClassPathChangedEventTests {
|
||||
|
||||
@Test
|
||||
public void changeSetMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new ClassPathChangedEvent(this.source, null, false))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new ClassPathChangedEvent(this.source, null, false))
|
||||
.withMessageContaining("ChangeSet must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getChangeSet() {
|
||||
Set<ChangedFiles> changeSet = new LinkedHashSet<>();
|
||||
ClassPathChangedEvent event = new ClassPathChangedEvent(this.source, changeSet,
|
||||
false);
|
||||
ClassPathChangedEvent event = new ClassPathChangedEvent(this.source, changeSet, false);
|
||||
assertThat(event.getChangeSet()).isSameAs(changeSet);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -67,16 +67,14 @@ public class ClassPathFileChangeListenerTests {
|
||||
@Test
|
||||
public void eventPublisherMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new ClassPathFileChangeListener(null,
|
||||
this.restartStrategy, this.fileSystemWatcher))
|
||||
.isThrownBy(() -> new ClassPathFileChangeListener(null, this.restartStrategy, this.fileSystemWatcher))
|
||||
.withMessageContaining("EventPublisher must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restartStrategyMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new ClassPathFileChangeListener(this.eventPublisher,
|
||||
null, this.fileSystemWatcher))
|
||||
.isThrownBy(() -> new ClassPathFileChangeListener(this.eventPublisher, null, this.fileSystemWatcher))
|
||||
.withMessageContaining("RestartStrategy must not be null");
|
||||
}
|
||||
|
||||
@@ -93,8 +91,8 @@ public class ClassPathFileChangeListenerTests {
|
||||
}
|
||||
|
||||
private void testSendsEvent(boolean restart) {
|
||||
ClassPathFileChangeListener listener = new ClassPathFileChangeListener(
|
||||
this.eventPublisher, this.restartStrategy, this.fileSystemWatcher);
|
||||
ClassPathFileChangeListener listener = new ClassPathFileChangeListener(this.eventPublisher,
|
||||
this.restartStrategy, this.fileSystemWatcher);
|
||||
File folder = new File("s1");
|
||||
File file = new File("f1");
|
||||
ChangedFile file1 = new ChangedFile(folder, file, ChangedFile.Type.ADD);
|
||||
@@ -109,8 +107,7 @@ public class ClassPathFileChangeListenerTests {
|
||||
}
|
||||
listener.onChange(changeSet);
|
||||
verify(this.eventPublisher).publishEvent(this.eventCaptor.capture());
|
||||
ClassPathChangedEvent actualEvent = (ClassPathChangedEvent) this.eventCaptor
|
||||
.getValue();
|
||||
ClassPathChangedEvent actualEvent = (ClassPathChangedEvent) this.eventCaptor.getValue();
|
||||
assertThat(actualEvent.getChangeSet()).isEqualTo(changeSet);
|
||||
assertThat(actualEvent.isRestartRequired()).isEqualTo(restart);
|
||||
}
|
||||
|
||||
@@ -55,8 +55,7 @@ public class ClassPathFileSystemWatcherTests {
|
||||
@Test
|
||||
public void urlsMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new ClassPathFileSystemWatcher(
|
||||
mock(FileSystemWatcherFactory.class),
|
||||
.isThrownBy(() -> new ClassPathFileSystemWatcher(mock(FileSystemWatcherFactory.class),
|
||||
mock(ClassPathRestartStrategy.class), (URL[]) null))
|
||||
.withMessageContaining("Urls must not be null");
|
||||
}
|
||||
@@ -86,8 +85,8 @@ public class ClassPathFileSystemWatcherTests {
|
||||
Thread.sleep(500);
|
||||
}
|
||||
assertThat(events.size()).isEqualTo(1);
|
||||
assertThat(events.get(0).getChangeSet().iterator().next().getFiles().iterator()
|
||||
.next().getFile()).isEqualTo(classFile);
|
||||
assertThat(events.get(0).getChangeSet().iterator().next().getFiles().iterator().next().getFile())
|
||||
.isEqualTo(classFile);
|
||||
context.close();
|
||||
}
|
||||
|
||||
@@ -102,11 +101,9 @@ public class ClassPathFileSystemWatcherTests {
|
||||
|
||||
@Bean
|
||||
public ClassPathFileSystemWatcher watcher() {
|
||||
FileSystemWatcher watcher = new FileSystemWatcher(false,
|
||||
Duration.ofMillis(100), Duration.ofMillis(10));
|
||||
FileSystemWatcher watcher = new FileSystemWatcher(false, Duration.ofMillis(100), Duration.ofMillis(10));
|
||||
URL[] urls = this.environment.getProperty("urls", URL[].class);
|
||||
return new ClassPathFileSystemWatcher(
|
||||
new MockFileSystemWatcherFactory(watcher), restartStrategy(), urls);
|
||||
return new ClassPathFileSystemWatcher(new MockFileSystemWatcherFactory(watcher), restartStrategy(), urls);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -136,8 +133,7 @@ public class ClassPathFileSystemWatcherTests {
|
||||
|
||||
}
|
||||
|
||||
private static class MockFileSystemWatcherFactory
|
||||
implements FileSystemWatcherFactory {
|
||||
private static class MockFileSystemWatcherFactory implements FileSystemWatcherFactory {
|
||||
|
||||
private final FileSystemWatcher watcher;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -76,8 +76,7 @@ public class PatternClassPathRestartStrategyTests {
|
||||
|
||||
@Test
|
||||
public void testChange() {
|
||||
ClassPathRestartStrategy strategy = createStrategy(
|
||||
"**/*Test.class,**/*Tests.class");
|
||||
ClassPathRestartStrategy strategy = createStrategy("**/*Test.class,**/*Tests.class");
|
||||
assertRestartRequired(strategy, "com/example/ExampleTests.class", false);
|
||||
assertRestartRequired(strategy, "com/example/ExampleTest.class", false);
|
||||
assertRestartRequired(strategy, "com/example/Example.class", true);
|
||||
@@ -87,10 +86,8 @@ public class PatternClassPathRestartStrategyTests {
|
||||
return new PatternClassPathRestartStrategy(pattern);
|
||||
}
|
||||
|
||||
private void assertRestartRequired(ClassPathRestartStrategy strategy,
|
||||
String relativeName, boolean expected) {
|
||||
assertThat(strategy.isRestartRequired(mockFile(relativeName)))
|
||||
.isEqualTo(expected);
|
||||
private void assertRestartRequired(ClassPathRestartStrategy strategy, String relativeName, boolean expected) {
|
||||
assertThat(strategy.isRestartRequired(mockFile(relativeName))).isEqualTo(expected);
|
||||
}
|
||||
|
||||
private ChangedFile mockFile(String relativeName) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -62,8 +62,7 @@ public class DevToolPropertiesIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void classPropertyConditionIsAffectedByDevToolProperties() {
|
||||
SpringApplication application = new SpringApplication(
|
||||
ClassConditionConfiguration.class);
|
||||
SpringApplication application = new SpringApplication(ClassConditionConfiguration.class);
|
||||
application.setWebApplicationType(WebApplicationType.NONE);
|
||||
this.context = application.run();
|
||||
this.context.getBean(ClassConditionConfiguration.class);
|
||||
@@ -71,8 +70,7 @@ public class DevToolPropertiesIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void beanMethodPropertyConditionIsAffectedByDevToolProperties() {
|
||||
SpringApplication application = new SpringApplication(
|
||||
BeanConditionConfiguration.class);
|
||||
SpringApplication application = new SpringApplication(BeanConditionConfiguration.class);
|
||||
application.setWebApplicationType(WebApplicationType.NONE);
|
||||
this.context = application.run();
|
||||
this.context.getBean(MyBean.class);
|
||||
@@ -82,8 +80,7 @@ public class DevToolPropertiesIntegrationTests {
|
||||
public void postProcessWhenRestarterDisabledAndRemoteSecretNotSetShouldNotAddPropertySource() {
|
||||
Restarter.clearInstance();
|
||||
Restarter.disable();
|
||||
SpringApplication application = new SpringApplication(
|
||||
BeanConditionConfiguration.class);
|
||||
SpringApplication application = new SpringApplication(BeanConditionConfiguration.class);
|
||||
application.setWebApplicationType(WebApplicationType.NONE);
|
||||
this.context = application.run();
|
||||
assertThatExceptionOfType(NoSuchBeanDefinitionException.class)
|
||||
@@ -94,11 +91,9 @@ public class DevToolPropertiesIntegrationTests {
|
||||
public void postProcessWhenRestarterDisabledAndRemoteSecretSetShouldAddPropertySource() {
|
||||
Restarter.clearInstance();
|
||||
Restarter.disable();
|
||||
SpringApplication application = new SpringApplication(
|
||||
BeanConditionConfiguration.class);
|
||||
SpringApplication application = new SpringApplication(BeanConditionConfiguration.class);
|
||||
application.setWebApplicationType(WebApplicationType.NONE);
|
||||
application.setDefaultProperties(
|
||||
Collections.singletonMap("spring.devtools.remote.secret", "donttell"));
|
||||
application.setDefaultProperties(Collections.singletonMap("spring.devtools.remote.secret", "donttell"));
|
||||
this.context = application.run();
|
||||
this.context.getBean(MyBean.class);
|
||||
}
|
||||
@@ -110,8 +105,7 @@ public class DevToolPropertiesIntegrationTests {
|
||||
this.context = application.run();
|
||||
ConfigurableEnvironment environment = this.context.getEnvironment();
|
||||
String property = environment.getProperty("server.error.include-stacktrace");
|
||||
assertThat(property)
|
||||
.isEqualTo(ErrorProperties.IncludeStacktrace.ALWAYS.toString());
|
||||
assertThat(property).isEqualTo(ErrorProperties.IncludeStacktrace.ALWAYS.toString());
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -54,8 +54,7 @@ public class DevToolsHomePropertiesPostProcessorTests {
|
||||
public void loadsHomeProperties() throws Exception {
|
||||
Properties properties = new Properties();
|
||||
properties.put("abc", "def");
|
||||
OutputStream out = new FileOutputStream(
|
||||
new File(this.home, ".spring-boot-devtools.properties"));
|
||||
OutputStream out = new FileOutputStream(new File(this.home, ".spring-boot-devtools.properties"));
|
||||
properties.store(out, null);
|
||||
out.close();
|
||||
ConfigurableEnvironment environment = new MockEnvironment();
|
||||
@@ -72,8 +71,7 @@ public class DevToolsHomePropertiesPostProcessorTests {
|
||||
assertThat(environment.getProperty("abc")).isNull();
|
||||
}
|
||||
|
||||
private class MockDevToolHomePropertiesPostProcessor
|
||||
extends DevToolsHomePropertiesPostProcessor {
|
||||
private class MockDevToolHomePropertiesPostProcessor extends DevToolsHomePropertiesPostProcessor {
|
||||
|
||||
@Override
|
||||
protected File getHomeFolder() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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,22 +39,20 @@ public class ChangedFileTests {
|
||||
|
||||
@Test
|
||||
public void sourceFolderMustNotBeNull() throws Exception {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new ChangedFile(null, this.temp.newFile(), Type.ADD))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new ChangedFile(null, this.temp.newFile(), Type.ADD))
|
||||
.withMessageContaining("SourceFolder must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileMustNotBeNull() throws Exception {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new ChangedFile(this.temp.newFolder(), null, Type.ADD))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new ChangedFile(this.temp.newFolder(), null, Type.ADD))
|
||||
.withMessageContaining("File must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeMustNotBeNull() throws Exception {
|
||||
assertThatIllegalArgumentException().isThrownBy(
|
||||
() -> new ChangedFile(this.temp.newFile(), this.temp.newFolder(), null))
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new ChangedFile(this.temp.newFile(), this.temp.newFolder(), null))
|
||||
.withMessageContaining("Type must not be null");
|
||||
}
|
||||
|
||||
@@ -67,8 +65,7 @@ public class ChangedFileTests {
|
||||
|
||||
@Test
|
||||
public void getType() throws Exception {
|
||||
ChangedFile changedFile = new ChangedFile(this.temp.newFolder(),
|
||||
this.temp.newFile(), Type.DELETE);
|
||||
ChangedFile changedFile = new ChangedFile(this.temp.newFolder(), this.temp.newFile(), Type.DELETE);
|
||||
assertThat(changedFile.getType()).isEqualTo(Type.DELETE);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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,8 +39,7 @@ public class FileSnapshotTests {
|
||||
|
||||
private static final long TWO_MINS = TimeUnit.MINUTES.toMillis(2);
|
||||
|
||||
private static final long MODIFIED = new Date().getTime()
|
||||
- TimeUnit.DAYS.toMillis(10);
|
||||
private static final long MODIFIED = new Date().getTime() - TimeUnit.DAYS.toMillis(10);
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
@@ -53,8 +52,7 @@ public class FileSnapshotTests {
|
||||
|
||||
@Test
|
||||
public void fileMustNotBeAFolder() throws Exception {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new FileSnapshot(this.temporaryFolder.newFolder()))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new FileSnapshot(this.temporaryFolder.newFolder()))
|
||||
.withMessageContaining("File must not be a folder");
|
||||
}
|
||||
|
||||
@@ -98,8 +96,7 @@ public class FileSnapshotTests {
|
||||
return file;
|
||||
}
|
||||
|
||||
private void setupFile(File file, String content, long lastModified)
|
||||
throws IOException {
|
||||
private void setupFile(File file, String content, long lastModified) throws IOException {
|
||||
FileCopyUtils.copy(content.getBytes(), file);
|
||||
file.setLastModified(lastModified);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -49,8 +49,7 @@ public class FileSystemWatcherTests {
|
||||
|
||||
private FileSystemWatcher watcher;
|
||||
|
||||
private List<Set<ChangedFiles>> changes = Collections
|
||||
.synchronizedList(new ArrayList<Set<ChangedFiles>>());
|
||||
private List<Set<ChangedFiles>> changes = Collections.synchronizedList(new ArrayList<Set<ChangedFiles>>());
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temp = new TemporaryFolder();
|
||||
@@ -63,47 +62,40 @@ public class FileSystemWatcherTests {
|
||||
@Test
|
||||
public void pollIntervalMustBePositive() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new FileSystemWatcher(true, Duration.ofMillis(0),
|
||||
Duration.ofMillis(1)))
|
||||
.isThrownBy(() -> new FileSystemWatcher(true, Duration.ofMillis(0), Duration.ofMillis(1)))
|
||||
.withMessageContaining("PollInterval must be positive");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void quietPeriodMustBePositive() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new FileSystemWatcher(true, Duration.ofMillis(1),
|
||||
Duration.ofMillis(0)))
|
||||
.isThrownBy(() -> new FileSystemWatcher(true, Duration.ofMillis(1), Duration.ofMillis(0)))
|
||||
.withMessageContaining("QuietPeriod must be positive");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pollIntervalMustBeGreaterThanQuietPeriod() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new FileSystemWatcher(true, Duration.ofMillis(1),
|
||||
Duration.ofMillis(1)))
|
||||
.isThrownBy(() -> new FileSystemWatcher(true, Duration.ofMillis(1), Duration.ofMillis(1)))
|
||||
.withMessageContaining("PollInterval must be greater than QuietPeriod");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listenerMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> this.watcher.addListener(null))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.watcher.addListener(null))
|
||||
.withMessageContaining("FileChangeListener must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cannotAddListenerToStartedListener() {
|
||||
this.watcher.start();
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(
|
||||
() -> this.watcher.addListener(mock(FileChangeListener.class)))
|
||||
assertThatIllegalStateException().isThrownBy(() -> this.watcher.addListener(mock(FileChangeListener.class)))
|
||||
.withMessageContaining("FileSystemWatcher already started");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sourceFolderMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> this.watcher.addSourceFolder(null))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.watcher.addSourceFolder(null))
|
||||
.withMessageContaining("Folder must not be null");
|
||||
}
|
||||
|
||||
@@ -111,16 +103,14 @@ public class FileSystemWatcherTests {
|
||||
public void sourceFolderMustNotBeAFile() {
|
||||
File folder = new File("pom.xml");
|
||||
assertThat(folder.isFile()).isTrue();
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> this.watcher.addSourceFolder(new File("pom.xml")))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.watcher.addSourceFolder(new File("pom.xml")))
|
||||
.withMessageContaining("Folder 'pom.xml' must not be a file");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cannotAddSourceFolderToStartedListener() throws Exception {
|
||||
this.watcher.start();
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> this.watcher.addSourceFolder(this.temp.newFolder()))
|
||||
assertThatIllegalStateException().isThrownBy(() -> this.watcher.addSourceFolder(this.temp.newFolder()))
|
||||
.withMessageContaining("FileSystemWatcher already started");
|
||||
}
|
||||
|
||||
@@ -262,8 +252,7 @@ public class FileSystemWatcherTests {
|
||||
File file = touch(new File(folder, "file.txt"));
|
||||
File trigger = touch(new File(folder, "trigger.txt"));
|
||||
this.watcher.addSourceFolder(folder);
|
||||
this.watcher.setTriggerFilter(
|
||||
(candidate) -> candidate.getName().equals("trigger.txt"));
|
||||
this.watcher.setTriggerFilter((candidate) -> candidate.getName().equals("trigger.txt"));
|
||||
this.watcher.start();
|
||||
FileCopyUtils.copy("abc".getBytes(), file);
|
||||
Thread.sleep(100);
|
||||
@@ -278,10 +267,8 @@ public class FileSystemWatcherTests {
|
||||
}
|
||||
|
||||
private void setupWatcher(long pollingInterval, long quietPeriod) {
|
||||
this.watcher = new FileSystemWatcher(false, Duration.ofMillis(pollingInterval),
|
||||
Duration.ofMillis(quietPeriod));
|
||||
this.watcher.addListener(
|
||||
(changeSet) -> FileSystemWatcherTests.this.changes.add(changeSet));
|
||||
this.watcher = new FileSystemWatcher(false, Duration.ofMillis(pollingInterval), Duration.ofMillis(quietPeriod));
|
||||
this.watcher.addListener((changeSet) -> FileSystemWatcherTests.this.changes.add(changeSet));
|
||||
}
|
||||
|
||||
private File startWithNewFolder() throws IOException {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -101,18 +101,15 @@ public class FolderSnapshotTests {
|
||||
|
||||
@Test
|
||||
public void getChangedFilesSnapshotMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> this.initialSnapshot.getChangedFiles(null, null))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.initialSnapshot.getChangedFiles(null, null))
|
||||
.withMessageContaining("Snapshot must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getChangedFilesSnapshotMustBeTheSameSourceFolder() throws Exception {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> this.initialSnapshot.getChangedFiles(
|
||||
new FolderSnapshot(createTestFolderStructure()), null))
|
||||
.withMessageContaining(
|
||||
"Snapshot source folder must be '" + this.folder + "'");
|
||||
assertThatIllegalArgumentException().isThrownBy(
|
||||
() -> this.initialSnapshot.getChangedFiles(new FolderSnapshot(createTestFolderStructure()), null))
|
||||
.withMessageContaining("Snapshot source folder must be '" + this.folder + "'");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -131,8 +128,7 @@ public class FolderSnapshotTests {
|
||||
file2.delete();
|
||||
newFile.createNewFile();
|
||||
FolderSnapshot updatedSnapshot = new FolderSnapshot(this.folder);
|
||||
ChangedFiles changedFiles = this.initialSnapshot.getChangedFiles(updatedSnapshot,
|
||||
null);
|
||||
ChangedFiles changedFiles = this.initialSnapshot.getChangedFiles(updatedSnapshot, null);
|
||||
assertThat(changedFiles.getSourceFolder()).isEqualTo(this.folder);
|
||||
assertThat(getChangedFile(changedFiles, file1).getType()).isEqualTo(Type.MODIFY);
|
||||
assertThat(getChangedFile(changedFiles, file2).getType()).isEqualTo(Type.DELETE);
|
||||
|
||||
@@ -67,8 +67,7 @@ public class HttpTunnelIntegrationTests {
|
||||
context.register(ServerConfiguration.class);
|
||||
context.refresh();
|
||||
String url = "http://localhost:" + context.getWebServer().getPort() + "/hello";
|
||||
ResponseEntity<String> entity = new TestRestTemplate().getForEntity(url,
|
||||
String.class);
|
||||
ResponseEntity<String> entity = new TestRestTemplate().getForEntity(url, String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(entity.getBody()).isEqualTo("Hello World");
|
||||
context.close();
|
||||
@@ -80,14 +79,11 @@ public class HttpTunnelIntegrationTests {
|
||||
serverContext.register(ServerConfiguration.class);
|
||||
serverContext.refresh();
|
||||
AnnotationConfigApplicationContext tunnelContext = new AnnotationConfigApplicationContext();
|
||||
TestPropertyValues.of("server.port:" + serverContext.getWebServer().getPort())
|
||||
.applyTo(tunnelContext);
|
||||
TestPropertyValues.of("server.port:" + serverContext.getWebServer().getPort()).applyTo(tunnelContext);
|
||||
tunnelContext.register(TunnelConfiguration.class);
|
||||
tunnelContext.refresh();
|
||||
String url = "http://localhost:"
|
||||
+ tunnelContext.getBean(TestTunnelClient.class).port + "/hello";
|
||||
ResponseEntity<String> entity = new TestRestTemplate().getForEntity(url,
|
||||
String.class);
|
||||
String url = "http://localhost:" + tunnelContext.getBean(TestTunnelClient.class).port + "/hello";
|
||||
ResponseEntity<String> entity = new TestRestTemplate().getForEntity(url, String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(entity.getBody()).isEqualTo("Hello World");
|
||||
serverContext.close();
|
||||
@@ -114,13 +110,11 @@ public class HttpTunnelIntegrationTests {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DispatcherFilter filter(
|
||||
AnnotationConfigServletWebServerApplicationContext context) {
|
||||
public DispatcherFilter filter(AnnotationConfigServletWebServerApplicationContext context) {
|
||||
TargetServerConnection connection = new SocketTargetServerConnection(
|
||||
() -> context.getWebServer().getPort());
|
||||
HttpTunnelServer server = new HttpTunnelServer(connection);
|
||||
HandlerMapper mapper = new UrlHandlerMapper("/httptunnel",
|
||||
new HttpTunnelServerHandler(server));
|
||||
HandlerMapper mapper = new UrlHandlerMapper("/httptunnel", new HttpTunnelServerHandler(server));
|
||||
Collection<HandlerMapper> mappers = Collections.singleton(mapper);
|
||||
Dispatcher dispatcher = new Dispatcher(AccessManager.PERMIT_ALL, mappers);
|
||||
return new DispatcherFilter(dispatcher);
|
||||
@@ -134,8 +128,7 @@ public class HttpTunnelIntegrationTests {
|
||||
@Bean
|
||||
public TunnelClient tunnelClient(@Value("${server.port}") int serverPort) {
|
||||
String url = "http://localhost:" + serverPort + "/httptunnel";
|
||||
TunnelConnection connection = new HttpTunnelConnection(url,
|
||||
new SimpleClientHttpRequestFactory());
|
||||
TunnelConnection connection = new HttpTunnelConnection(url, new SimpleClientHttpRequestFactory());
|
||||
return new TestTunnelClient(0, connection);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -40,20 +40,17 @@ public class ConnectionInputStreamTests {
|
||||
public void readHeader() throws Exception {
|
||||
String header = "";
|
||||
for (int i = 0; i < 100; i++) {
|
||||
header += "x-something-" + i
|
||||
+ ": xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
header += "x-something-" + i + ": xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
}
|
||||
String data = header + "\r\n\r\n" + "content\r\n";
|
||||
ConnectionInputStream inputStream = new ConnectionInputStream(
|
||||
new ByteArrayInputStream(data.getBytes()));
|
||||
ConnectionInputStream inputStream = new ConnectionInputStream(new ByteArrayInputStream(data.getBytes()));
|
||||
assertThat(inputStream.readHeader()).isEqualTo(header);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readFully() throws Exception {
|
||||
byte[] bytes = "the data that we want to read fully".getBytes();
|
||||
LimitedInputStream source = new LimitedInputStream(
|
||||
new ByteArrayInputStream(bytes), 2);
|
||||
LimitedInputStream source = new LimitedInputStream(new ByteArrayInputStream(bytes), 2);
|
||||
ConnectionInputStream inputStream = new ConnectionInputStream(source);
|
||||
byte[] buffer = new byte[bytes.length];
|
||||
inputStream.readFully(buffer, 0, buffer.length);
|
||||
@@ -62,19 +59,15 @@ public class ConnectionInputStreamTests {
|
||||
|
||||
@Test
|
||||
public void checkedRead() throws Exception {
|
||||
ConnectionInputStream inputStream = new ConnectionInputStream(
|
||||
new ByteArrayInputStream(NO_BYTES));
|
||||
assertThatIOException().isThrownBy(inputStream::checkedRead)
|
||||
.withMessageContaining("End of stream");
|
||||
ConnectionInputStream inputStream = new ConnectionInputStream(new ByteArrayInputStream(NO_BYTES));
|
||||
assertThatIOException().isThrownBy(inputStream::checkedRead).withMessageContaining("End of stream");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkedReadArray() throws Exception {
|
||||
byte[] buffer = new byte[100];
|
||||
ConnectionInputStream inputStream = new ConnectionInputStream(
|
||||
new ByteArrayInputStream(NO_BYTES));
|
||||
assertThatIOException()
|
||||
.isThrownBy(() -> inputStream.checkedRead(buffer, 0, buffer.length))
|
||||
ConnectionInputStream inputStream = new ConnectionInputStream(new ByteArrayInputStream(NO_BYTES));
|
||||
assertThatIOException().isThrownBy(() -> inputStream.checkedRead(buffer, 0, buffer.length))
|
||||
.withMessageContaining("End of stream");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -41,8 +41,7 @@ public class FrameTests {
|
||||
|
||||
@Test
|
||||
public void typeMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new Frame((Frame.Type) null))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new Frame((Frame.Type) null))
|
||||
.withMessageContaining("Type must not be null");
|
||||
}
|
||||
|
||||
@@ -88,16 +87,14 @@ public class FrameTests {
|
||||
@Test
|
||||
public void readFragmentedNotSupported() throws Exception {
|
||||
byte[] bytes = new byte[] { 0x0F };
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> Frame.read(newConnectionInputStream(bytes)))
|
||||
assertThatIllegalStateException().isThrownBy(() -> Frame.read(newConnectionInputStream(bytes)))
|
||||
.withMessageContaining("Fragmented frames are not supported");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readLargeFramesNotSupported() throws Exception {
|
||||
byte[] bytes = new byte[] { (byte) 0x80, (byte) 0xFF };
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> Frame.read(newConnectionInputStream(bytes)))
|
||||
assertThatIllegalStateException().isThrownBy(() -> Frame.read(newConnectionInputStream(bytes)))
|
||||
.withMessageContaining("Large frames are not supported");
|
||||
}
|
||||
|
||||
@@ -111,8 +108,7 @@ public class FrameTests {
|
||||
|
||||
@Test
|
||||
public void readMaskedTextFrame() throws Exception {
|
||||
byte[] bytes = new byte[] { (byte) 0x81, (byte) 0x82, 0x0F, 0x0F, 0x0F, 0x0F,
|
||||
0x4E, 0x4E };
|
||||
byte[] bytes = new byte[] { (byte) 0x81, (byte) 0x82, 0x0F, 0x0F, 0x0F, 0x0F, 0x4E, 0x4E };
|
||||
Frame frame = Frame.read(newConnectionInputStream(bytes));
|
||||
assertThat(frame.getType()).isEqualTo(Frame.Type.TEXT);
|
||||
assertThat(frame.getPayload()).isEqualTo(new byte[] { 0x41, 0x41 });
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -85,8 +85,7 @@ public class LiveReloadServerTests {
|
||||
this.server.triggerReload();
|
||||
Thread.sleep(200);
|
||||
this.server.stop();
|
||||
assertThat(handler.getMessages().get(0))
|
||||
.contains("http://livereload.com/protocols/official-7");
|
||||
assertThat(handler.getMessages().get(0)).contains("http://livereload.com/protocols/official-7");
|
||||
assertThat(handler.getMessages().get(1)).contains("command\":\"reload\"");
|
||||
}
|
||||
|
||||
@@ -109,8 +108,7 @@ public class LiveReloadServerTests {
|
||||
|
||||
private void awaitClosedException() throws InterruptedException {
|
||||
long startTime = System.currentTimeMillis();
|
||||
while (this.server.getClosedExceptions().isEmpty()
|
||||
&& System.currentTimeMillis() - startTime < 10000) {
|
||||
while (this.server.getClosedExceptions().isEmpty() && System.currentTimeMillis() - startTime < 10000) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
}
|
||||
@@ -164,8 +162,8 @@ public class LiveReloadServerTests {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Connection createConnection(java.net.Socket socket,
|
||||
InputStream inputStream, OutputStream outputStream) throws IOException {
|
||||
protected Connection createConnection(java.net.Socket socket, InputStream inputStream,
|
||||
OutputStream outputStream) throws IOException {
|
||||
return new MonitoredConnection(socket, inputStream, outputStream);
|
||||
}
|
||||
|
||||
@@ -177,8 +175,8 @@ public class LiveReloadServerTests {
|
||||
|
||||
private class MonitoredConnection extends Connection {
|
||||
|
||||
MonitoredConnection(java.net.Socket socket, InputStream inputStream,
|
||||
OutputStream outputStream) throws IOException {
|
||||
MonitoredConnection(java.net.Socket socket, InputStream inputStream, OutputStream outputStream)
|
||||
throws IOException {
|
||||
super(socket, inputStream, outputStream);
|
||||
}
|
||||
|
||||
@@ -212,8 +210,7 @@ public class LiveReloadServerTests {
|
||||
private CloseStatus closeStatus;
|
||||
|
||||
@Override
|
||||
public void afterConnectionEstablished(WebSocketSession session)
|
||||
throws Exception {
|
||||
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
|
||||
this.session = session;
|
||||
session.sendMessage(new TextMessage(HANDSHAKE));
|
||||
this.helloLatch.countDown();
|
||||
|
||||
@@ -65,37 +65,32 @@ public class ClassPathChangeUploaderTests {
|
||||
@Before
|
||||
public void setup() {
|
||||
this.requestFactory = new MockClientHttpRequestFactory();
|
||||
this.uploader = new ClassPathChangeUploader("http://localhost/upload",
|
||||
this.requestFactory);
|
||||
this.uploader = new ClassPathChangeUploader("http://localhost/upload", this.requestFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urlMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new ClassPathChangeUploader(null, this.requestFactory))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new ClassPathChangeUploader(null, this.requestFactory))
|
||||
.withMessageContaining("URL must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urlMustNotBeEmpty() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new ClassPathChangeUploader("", this.requestFactory))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new ClassPathChangeUploader("", this.requestFactory))
|
||||
.withMessageContaining("URL must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestFactoryMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(
|
||||
() -> new ClassPathChangeUploader("http://localhost:8080", null))
|
||||
.isThrownBy(() -> new ClassPathChangeUploader("http://localhost:8080", null))
|
||||
.withMessageContaining("RequestFactory must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urlMustNotBeMalformed() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new ClassPathChangeUploader("htttttp:///ttest",
|
||||
this.requestFactory))
|
||||
.isThrownBy(() -> new ClassPathChangeUploader("htttttp:///ttest", this.requestFactory))
|
||||
.withMessageContaining("Malformed URL 'htttttp:///ttest'");
|
||||
}
|
||||
|
||||
@@ -118,8 +113,7 @@ public class ClassPathChangeUploaderTests {
|
||||
this.requestFactory.willRespond(HttpStatus.OK);
|
||||
this.uploader.onApplicationEvent(event);
|
||||
assertThat(this.requestFactory.getExecutedRequests()).hasSize(2);
|
||||
verifyUploadRequest(sourceFolder,
|
||||
this.requestFactory.getExecutedRequests().get(1));
|
||||
verifyUploadRequest(sourceFolder, this.requestFactory.getExecutedRequests().get(1));
|
||||
}
|
||||
|
||||
private void verifyUploadRequest(File sourceFolder, MockClientHttpRequest request)
|
||||
@@ -137,13 +131,11 @@ public class ClassPathChangeUploaderTests {
|
||||
}
|
||||
|
||||
private void assertClassFile(ClassLoaderFile file, String content, Kind kind) {
|
||||
assertThat(file.getContents())
|
||||
.isEqualTo((content != null) ? content.getBytes() : null);
|
||||
assertThat(file.getContents()).isEqualTo((content != null) ? content.getBytes() : null);
|
||||
assertThat(file.getKind()).isEqualTo(kind);
|
||||
}
|
||||
|
||||
private ClassPathChangedEvent createClassPathChangedEvent(File sourceFolder)
|
||||
throws IOException {
|
||||
private ClassPathChangedEvent createClassPathChangedEvent(File sourceFolder) throws IOException {
|
||||
Set<ChangedFile> files = new LinkedHashSet<>();
|
||||
File file1 = createFile(sourceFolder, "File1");
|
||||
File file2 = createFile(sourceFolder, "File2");
|
||||
@@ -163,10 +155,8 @@ public class ClassPathChangeUploaderTests {
|
||||
return file;
|
||||
}
|
||||
|
||||
private ClassLoaderFiles deserialize(byte[] bytes)
|
||||
throws IOException, ClassNotFoundException {
|
||||
ObjectInputStream objectInputStream = new ObjectInputStream(
|
||||
new ByteArrayInputStream(bytes));
|
||||
private ClassLoaderFiles deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
|
||||
ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(bytes));
|
||||
return (ClassLoaderFiles) objectInputStream.readObject();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -71,47 +71,42 @@ public class DelayedLiveReloadTriggerTests {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
given(this.errorRequest.execute()).willReturn(this.errorResponse);
|
||||
given(this.okRequest.execute()).willReturn(this.okResponse);
|
||||
given(this.errorResponse.getStatusCode())
|
||||
.willReturn(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
given(this.errorResponse.getStatusCode()).willReturn(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
given(this.okResponse.getStatusCode()).willReturn(HttpStatus.OK);
|
||||
this.trigger = new DelayedLiveReloadTrigger(this.liveReloadServer,
|
||||
this.requestFactory, URL);
|
||||
this.trigger = new DelayedLiveReloadTrigger(this.liveReloadServer, this.requestFactory, URL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void liveReloadServerMustNotBeNull() {
|
||||
assertThatIllegalArgumentException().isThrownBy(
|
||||
() -> new DelayedLiveReloadTrigger(null, this.requestFactory, URL))
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new DelayedLiveReloadTrigger(null, this.requestFactory, URL))
|
||||
.withMessageContaining("LiveReloadServer must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestFactoryMustNotBeNull() {
|
||||
assertThatIllegalArgumentException().isThrownBy(
|
||||
() -> new DelayedLiveReloadTrigger(this.liveReloadServer, null, URL))
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new DelayedLiveReloadTrigger(this.liveReloadServer, null, URL))
|
||||
.withMessageContaining("RequestFactory must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urlMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new DelayedLiveReloadTrigger(this.liveReloadServer,
|
||||
this.requestFactory, null))
|
||||
.isThrownBy(() -> new DelayedLiveReloadTrigger(this.liveReloadServer, this.requestFactory, null))
|
||||
.withMessageContaining("URL must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urlMustNotBeEmpty() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new DelayedLiveReloadTrigger(this.liveReloadServer,
|
||||
this.requestFactory, ""))
|
||||
.isThrownBy(() -> new DelayedLiveReloadTrigger(this.liveReloadServer, this.requestFactory, ""))
|
||||
.withMessageContaining("URL must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void triggerReloadOnStatus() throws Exception {
|
||||
given(this.requestFactory.createRequest(new URI(URL), HttpMethod.GET))
|
||||
.willThrow(new IOException())
|
||||
given(this.requestFactory.createRequest(new URI(URL), HttpMethod.GET)).willThrow(new IOException())
|
||||
.willReturn(this.errorRequest, this.okRequest);
|
||||
long startTime = System.currentTimeMillis();
|
||||
this.trigger.setTimings(10, 200, 30000);
|
||||
@@ -122,8 +117,7 @@ public class DelayedLiveReloadTriggerTests {
|
||||
|
||||
@Test
|
||||
public void timeout() throws Exception {
|
||||
given(this.requestFactory.createRequest(new URI(URL), HttpMethod.GET))
|
||||
.willThrow(new IOException());
|
||||
given(this.requestFactory.createRequest(new URI(URL), HttpMethod.GET)).willThrow(new IOException());
|
||||
this.trigger.setTimings(10, 0, 10);
|
||||
this.trigger.run();
|
||||
verify(this.liveReloadServer, never()).triggerReload();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -73,36 +73,31 @@ public class HttpHeaderInterceptorTests {
|
||||
|
||||
@Test
|
||||
public void constructorNullHeaderName() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new HttpHeaderInterceptor(null, this.value))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new HttpHeaderInterceptor(null, this.value))
|
||||
.withMessageContaining("Name must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorEmptyHeaderName() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new HttpHeaderInterceptor("", this.value))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new HttpHeaderInterceptor("", this.value))
|
||||
.withMessageContaining("Name must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorNullHeaderValue() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new HttpHeaderInterceptor(this.name, null))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new HttpHeaderInterceptor(this.name, null))
|
||||
.withMessageContaining("Value must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorEmptyHeaderValue() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new HttpHeaderInterceptor(this.name, ""))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new HttpHeaderInterceptor(this.name, ""))
|
||||
.withMessageContaining("Value must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void intercept() throws IOException {
|
||||
ClientHttpResponse result = this.interceptor.intercept(this.request, this.body,
|
||||
this.execution);
|
||||
ClientHttpResponse result = this.interceptor.intercept(this.request, this.body, this.execution);
|
||||
assertThat(this.request.getHeaders().getFirst(this.name)).isEqualTo(this.value);
|
||||
assertThat(result).isEqualTo(this.response);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -101,8 +101,7 @@ public class RemoteClientConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void failIfNoSecret() {
|
||||
assertThatExceptionOfType(BeanCreationException.class)
|
||||
.isThrownBy(() -> configure("http://localhost", false))
|
||||
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() -> configure("http://localhost", false))
|
||||
.withMessageContaining("required to secure your connection");
|
||||
}
|
||||
|
||||
@@ -112,8 +111,7 @@ public class RemoteClientConfigurationTests {
|
||||
Set<ChangedFiles> changeSet = new HashSet<>();
|
||||
ClassPathChangedEvent event = new ClassPathChangedEvent(this, changeSet, false);
|
||||
this.clientContext.publishEvent(event);
|
||||
LiveReloadConfiguration configuration = this.clientContext
|
||||
.getBean(LiveReloadConfiguration.class);
|
||||
LiveReloadConfiguration configuration = this.clientContext.getBean(LiveReloadConfiguration.class);
|
||||
configuration.getExecutor().shutdown();
|
||||
configuration.getExecutor().awaitTermination(2, TimeUnit.SECONDS);
|
||||
LiveReloadServer server = this.clientContext.getBean(LiveReloadServer.class);
|
||||
@@ -142,8 +140,7 @@ public class RemoteClientConfigurationTests {
|
||||
this.context = new AnnotationConfigServletWebServerApplicationContext();
|
||||
this.context.register(Config.class);
|
||||
if (setSecret) {
|
||||
TestPropertyValues.of("spring.devtools.remote.secret:secret")
|
||||
.applyTo(this.context);
|
||||
TestPropertyValues.of("spring.devtools.remote.secret:secret").applyTo(this.context);
|
||||
}
|
||||
this.context.refresh();
|
||||
this.clientContext = new AnnotationConfigApplicationContext();
|
||||
@@ -151,11 +148,9 @@ public class RemoteClientConfigurationTests {
|
||||
new RestartScopeInitializer().initialize(this.clientContext);
|
||||
this.clientContext.register(ClientConfig.class, RemoteClientConfiguration.class);
|
||||
if (setSecret) {
|
||||
TestPropertyValues.of("spring.devtools.remote.secret:secret")
|
||||
.applyTo(this.clientContext);
|
||||
TestPropertyValues.of("spring.devtools.remote.secret:secret").applyTo(this.clientContext);
|
||||
}
|
||||
String remoteUrlProperty = "remoteUrl:" + remoteUrl + ":"
|
||||
+ this.context.getWebServer().getPort();
|
||||
String remoteUrlProperty = "remoteUrl:" + remoteUrl + ":" + this.context.getWebServer().getPort();
|
||||
TestPropertyValues.of(remoteUrlProperty).applyTo(this.clientContext);
|
||||
this.clientContext.refresh();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -98,12 +98,10 @@ public class DispatcherFilterTests {
|
||||
public void handledByDispatcher() throws Exception {
|
||||
HttpServletRequest request = new MockHttpServletRequest("GET", "/hello");
|
||||
HttpServletResponse response = new MockHttpServletResponse();
|
||||
willReturn(true).given(this.dispatcher).handle(any(ServerHttpRequest.class),
|
||||
any(ServerHttpResponse.class));
|
||||
willReturn(true).given(this.dispatcher).handle(any(ServerHttpRequest.class), any(ServerHttpResponse.class));
|
||||
this.filter.doFilter(request, response, this.chain);
|
||||
verifyZeroInteractions(this.chain);
|
||||
verify(this.dispatcher).handle(this.serverRequestCaptor.capture(),
|
||||
this.serverResponseCaptor.capture());
|
||||
verify(this.dispatcher).handle(this.serverRequestCaptor.capture(), this.serverResponseCaptor.capture());
|
||||
ServerHttpRequest dispatcherRequest = this.serverRequestCaptor.getValue();
|
||||
ServletServerHttpRequest actualRequest = (ServletServerHttpRequest) dispatcherRequest;
|
||||
ServerHttpResponse dispatcherResponse = this.serverResponseCaptor.getValue();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -73,27 +73,23 @@ public class DispatcherTests {
|
||||
|
||||
@Test
|
||||
public void accessManagerMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new Dispatcher(null, Collections.emptyList()))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new Dispatcher(null, Collections.emptyList()))
|
||||
.withMessageContaining("AccessManager must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mappersMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new Dispatcher(this.accessManager, null))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new Dispatcher(this.accessManager, null))
|
||||
.withMessageContaining("Mappers must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void accessManagerVetoRequest() throws Exception {
|
||||
given(this.accessManager.isAllowed(any(ServerHttpRequest.class)))
|
||||
.willReturn(false);
|
||||
given(this.accessManager.isAllowed(any(ServerHttpRequest.class))).willReturn(false);
|
||||
HandlerMapper mapper = mock(HandlerMapper.class);
|
||||
Handler handler = mock(Handler.class);
|
||||
given(mapper.getHandler(any(ServerHttpRequest.class))).willReturn(handler);
|
||||
Dispatcher dispatcher = new Dispatcher(this.accessManager,
|
||||
Collections.singleton(mapper));
|
||||
Dispatcher dispatcher = new Dispatcher(this.accessManager, Collections.singleton(mapper));
|
||||
dispatcher.handle(this.serverRequest, this.serverResponse);
|
||||
verifyZeroInteractions(handler);
|
||||
assertThat(this.response.getStatus()).isEqualTo(403);
|
||||
@@ -101,23 +97,19 @@ public class DispatcherTests {
|
||||
|
||||
@Test
|
||||
public void accessManagerAllowRequest() throws Exception {
|
||||
given(this.accessManager.isAllowed(any(ServerHttpRequest.class)))
|
||||
.willReturn(true);
|
||||
given(this.accessManager.isAllowed(any(ServerHttpRequest.class))).willReturn(true);
|
||||
HandlerMapper mapper = mock(HandlerMapper.class);
|
||||
Handler handler = mock(Handler.class);
|
||||
given(mapper.getHandler(any(ServerHttpRequest.class))).willReturn(handler);
|
||||
Dispatcher dispatcher = new Dispatcher(this.accessManager,
|
||||
Collections.singleton(mapper));
|
||||
Dispatcher dispatcher = new Dispatcher(this.accessManager, Collections.singleton(mapper));
|
||||
dispatcher.handle(this.serverRequest, this.serverResponse);
|
||||
verify(handler).handle(this.serverRequest, this.serverResponse);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ordersMappers() throws Exception {
|
||||
HandlerMapper mapper1 = mock(HandlerMapper.class,
|
||||
withSettings().extraInterfaces(Ordered.class));
|
||||
HandlerMapper mapper2 = mock(HandlerMapper.class,
|
||||
withSettings().extraInterfaces(Ordered.class));
|
||||
HandlerMapper mapper1 = mock(HandlerMapper.class, withSettings().extraInterfaces(Ordered.class));
|
||||
HandlerMapper mapper2 = mock(HandlerMapper.class, withSettings().extraInterfaces(Ordered.class));
|
||||
given(((Ordered) mapper1).getOrder()).willReturn(1);
|
||||
given(((Ordered) mapper2).getOrder()).willReturn(2);
|
||||
List<HandlerMapper> mappers = Arrays.asList(mapper2, mapper1);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -53,29 +53,25 @@ public class HttpHeaderAccessManagerTests {
|
||||
|
||||
@Test
|
||||
public void headerNameMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new HttpHeaderAccessManager(null, SECRET))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new HttpHeaderAccessManager(null, SECRET))
|
||||
.withMessageContaining("HeaderName must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headerNameMustNotBeEmpty() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new HttpHeaderAccessManager("", SECRET))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new HttpHeaderAccessManager("", SECRET))
|
||||
.withMessageContaining("HeaderName must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void expectedSecretMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new HttpHeaderAccessManager(HEADER, null))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new HttpHeaderAccessManager(HEADER, null))
|
||||
.withMessageContaining("ExpectedSecret must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void expectedSecretMustNotBeEmpty() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new HttpHeaderAccessManager(HEADER, ""))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new HttpHeaderAccessManager(HEADER, ""))
|
||||
.withMessageContaining("ExpectedSecret must not be empty");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -40,22 +40,19 @@ public class UrlHandlerMapperTests {
|
||||
|
||||
@Test
|
||||
public void requestUriMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new UrlHandlerMapper(null, this.handler))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new UrlHandlerMapper(null, this.handler))
|
||||
.withMessageContaining("URL must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestUriMustNotBeEmpty() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new UrlHandlerMapper("", this.handler))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new UrlHandlerMapper("", this.handler))
|
||||
.withMessageContaining("URL must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestUrlMustStartWithSlash() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new UrlHandlerMapper("tunnel", this.handler))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new UrlHandlerMapper("tunnel", this.handler))
|
||||
.withMessageContaining("URL must start with '/'");
|
||||
}
|
||||
|
||||
@@ -70,8 +67,7 @@ public class UrlHandlerMapperTests {
|
||||
@Test
|
||||
public void ignoresDifferentUrl() {
|
||||
UrlHandlerMapper mapper = new UrlHandlerMapper("/tunnel", this.handler);
|
||||
HttpServletRequest servletRequest = new MockHttpServletRequest("GET",
|
||||
"/tunnel/other");
|
||||
HttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/tunnel/other");
|
||||
ServerHttpRequest request = new ServletServerHttpRequest(servletRequest);
|
||||
assertThat(mapper.getHandler(request)).isNull();
|
||||
}
|
||||
|
||||
@@ -71,9 +71,8 @@ public class ChangeableUrlsTests {
|
||||
|
||||
@Test
|
||||
public void skipsUrls() throws Exception {
|
||||
ChangeableUrls urls = ChangeableUrls.fromUrls(makeUrl("spring-boot"),
|
||||
makeUrl("spring-boot-autoconfigure"), makeUrl("spring-boot-actuator"),
|
||||
makeUrl("spring-boot-starter"),
|
||||
ChangeableUrls urls = ChangeableUrls.fromUrls(makeUrl("spring-boot"), makeUrl("spring-boot-autoconfigure"),
|
||||
makeUrl("spring-boot-actuator"), makeUrl("spring-boot-starter"),
|
||||
makeUrl("spring-boot-starter-some-thing"));
|
||||
assertThat(urls).isEmpty();
|
||||
}
|
||||
@@ -82,19 +81,16 @@ public class ChangeableUrlsTests {
|
||||
public void urlsFromJarClassPathAreConsidered() throws Exception {
|
||||
File relative = this.temporaryFolder.newFolder();
|
||||
URL absoluteUrl = this.temporaryFolder.newFolder().toURI().toURL();
|
||||
File jarWithClassPath = makeJarFileWithUrlsInManifestClassPath(
|
||||
"project-core/target/classes/", "project-web/target/classes/",
|
||||
"does-not-exist/target/classes", relative.getName() + "/", absoluteUrl);
|
||||
new File(jarWithClassPath.getParentFile(), "project-core/target/classes")
|
||||
.mkdirs();
|
||||
File jarWithClassPath = makeJarFileWithUrlsInManifestClassPath("project-core/target/classes/",
|
||||
"project-web/target/classes/", "does-not-exist/target/classes", relative.getName() + "/", absoluteUrl);
|
||||
new File(jarWithClassPath.getParentFile(), "project-core/target/classes").mkdirs();
|
||||
new File(jarWithClassPath.getParentFile(), "project-web/target/classes").mkdirs();
|
||||
ChangeableUrls urls = ChangeableUrls
|
||||
.fromClassLoader(new URLClassLoader(new URL[] {
|
||||
jarWithClassPath.toURI().toURL(), makeJarFileWithNoManifest() }));
|
||||
ChangeableUrls urls = ChangeableUrls.fromClassLoader(
|
||||
new URLClassLoader(new URL[] { jarWithClassPath.toURI().toURL(), makeJarFileWithNoManifest() }));
|
||||
assertThat(urls.toList()).containsExactly(
|
||||
new URL(jarWithClassPath.toURI().toURL(), "project-core/target/classes/"),
|
||||
new URL(jarWithClassPath.toURI().toURL(), "project-web/target/classes/"),
|
||||
relative.toURI().toURL(), absoluteUrl);
|
||||
new URL(jarWithClassPath.toURI().toURL(), "project-web/target/classes/"), relative.toURI().toURL(),
|
||||
absoluteUrl);
|
||||
}
|
||||
|
||||
private URL makeUrl(String name) throws IOException {
|
||||
@@ -109,8 +105,7 @@ public class ChangeableUrlsTests {
|
||||
private File makeJarFileWithUrlsInManifestClassPath(Object... urls) throws Exception {
|
||||
File classpathJar = this.temporaryFolder.newFile("classpath.jar");
|
||||
Manifest manifest = new Manifest();
|
||||
manifest.getMainAttributes().putValue(Attributes.Name.MANIFEST_VERSION.toString(),
|
||||
"1.0");
|
||||
manifest.getMainAttributes().putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1.0");
|
||||
manifest.getMainAttributes().putValue(Attributes.Name.CLASS_PATH.toString(),
|
||||
StringUtils.arrayToDelimitedString(urls, " "));
|
||||
new JarOutputStream(new FileOutputStream(classpathJar), manifest).close();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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,8 +64,7 @@ public class ClassLoaderFilesResourcePatternResolverTests {
|
||||
@Before
|
||||
public void setup() {
|
||||
this.files = new ClassLoaderFiles();
|
||||
this.resolver = new ClassLoaderFilesResourcePatternResolver(
|
||||
new GenericApplicationContext(), this.files);
|
||||
this.resolver = new ClassLoaderFilesResourcePatternResolver(new GenericApplicationContext(), this.files);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -81,8 +80,7 @@ public class ClassLoaderFilesResourcePatternResolverTests {
|
||||
|
||||
@Test
|
||||
public void getResourceWhenHasServletContextShouldReturnServletResource() {
|
||||
GenericWebApplicationContext context = new GenericWebApplicationContext(
|
||||
new MockServletContext());
|
||||
GenericWebApplicationContext context = new GenericWebApplicationContext(new MockServletContext());
|
||||
this.resolver = new ClassLoaderFilesResourcePatternResolver(context, this.files);
|
||||
Resource resource = this.resolver.getResource("index.html");
|
||||
assertThat(resource).isNotNull().isInstanceOf(ServletContextResource.class);
|
||||
@@ -92,19 +90,16 @@ public class ClassLoaderFilesResourcePatternResolverTests {
|
||||
public void getResourceWhenDeletedShouldReturnDeletedResource() throws Exception {
|
||||
File folder = this.temp.newFolder();
|
||||
File file = createFile(folder, "name.class");
|
||||
this.files.addFile(folder.getName(), "name.class",
|
||||
new ClassLoaderFile(Kind.DELETED, null));
|
||||
this.files.addFile(folder.getName(), "name.class", new ClassLoaderFile(Kind.DELETED, null));
|
||||
Resource resource = this.resolver.getResource("file:" + file.getAbsolutePath());
|
||||
assertThat(resource).isNotNull()
|
||||
.isInstanceOf(DeletedClassLoaderFileResource.class);
|
||||
assertThat(resource).isNotNull().isInstanceOf(DeletedClassLoaderFileResource.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getResourcesShouldReturnResources() throws Exception {
|
||||
File folder = this.temp.newFolder();
|
||||
createFile(folder, "name.class");
|
||||
Resource[] resources = this.resolver
|
||||
.getResources("file:" + folder.getAbsolutePath() + "/**");
|
||||
Resource[] resources = this.resolver.getResources("file:" + folder.getAbsolutePath() + "/**");
|
||||
assertThat(resources).isNotEmpty();
|
||||
}
|
||||
|
||||
@@ -112,10 +107,8 @@ public class ClassLoaderFilesResourcePatternResolverTests {
|
||||
public void getResourcesWhenDeletedShouldFilterDeleted() throws Exception {
|
||||
File folder = this.temp.newFolder();
|
||||
createFile(folder, "name.class");
|
||||
this.files.addFile(folder.getName(), "name.class",
|
||||
new ClassLoaderFile(Kind.DELETED, null));
|
||||
Resource[] resources = this.resolver
|
||||
.getResources("file:" + folder.getAbsolutePath() + "/**");
|
||||
this.files.addFile(folder.getName(), "name.class", new ClassLoaderFile(Kind.DELETED, null));
|
||||
Resource[] resources = this.resolver.getResources("file:" + folder.getAbsolutePath() + "/**");
|
||||
assertThat(resources).isEmpty();
|
||||
}
|
||||
|
||||
@@ -143,8 +136,7 @@ public class ClassLoaderFilesResourcePatternResolverTests {
|
||||
|
||||
@Test
|
||||
public void customResourceLoaderIsUsedInWebApplication() {
|
||||
GenericWebApplicationContext context = new GenericWebApplicationContext(
|
||||
new MockServletContext());
|
||||
GenericWebApplicationContext context = new GenericWebApplicationContext(new MockServletContext());
|
||||
ResourceLoader resourceLoader = mock(ResourceLoader.class);
|
||||
context.setResourceLoader(resourceLoader);
|
||||
this.resolver = new ClassLoaderFilesResourcePatternResolver(context, this.files);
|
||||
@@ -154,8 +146,7 @@ public class ClassLoaderFilesResourcePatternResolverTests {
|
||||
|
||||
@Test
|
||||
public void customProtocolResolverIsUsedInWebApplication() {
|
||||
GenericWebApplicationContext context = new GenericWebApplicationContext(
|
||||
new MockServletContext());
|
||||
GenericWebApplicationContext context = new GenericWebApplicationContext(new MockServletContext());
|
||||
Resource resource = mock(Resource.class);
|
||||
ProtocolResolver resolver = mockProtocolResolver("foo:some-file.txt", resource);
|
||||
context.addProtocolResolver(resolver);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -74,8 +74,7 @@ public class DefaultRestartInitializerTests {
|
||||
@Test
|
||||
public void threadNotUsingAppClassLoader() {
|
||||
DefaultRestartInitializer initializer = new DefaultRestartInitializer();
|
||||
ClassLoader classLoader = new MockLauncherClassLoader(
|
||||
getClass().getClassLoader());
|
||||
ClassLoader classLoader = new MockLauncherClassLoader(getClass().getClassLoader());
|
||||
Thread thread = new Thread();
|
||||
thread.setName("main");
|
||||
thread.setContextClassLoader(classLoader);
|
||||
@@ -84,8 +83,7 @@ public class DefaultRestartInitializerTests {
|
||||
|
||||
@Test
|
||||
public void urlsCanBeRetrieved() {
|
||||
assertThat(new DefaultRestartInitializer().getUrls(Thread.currentThread()))
|
||||
.isNotEmpty();
|
||||
assertThat(new DefaultRestartInitializer().getUrls(Thread.currentThread())).isNotEmpty();
|
||||
}
|
||||
|
||||
protected void testSkippedStacks(String s) {
|
||||
@@ -93,8 +91,7 @@ public class DefaultRestartInitializerTests {
|
||||
ClassLoader classLoader = new MockAppClassLoader(getClass().getClassLoader());
|
||||
Thread thread = mock(Thread.class);
|
||||
thread.setName("main");
|
||||
StackTraceElement element = new StackTraceElement(s, "someMethod", "someFile",
|
||||
123);
|
||||
StackTraceElement element = new StackTraceElement(s, "someMethod", "someFile", 123);
|
||||
given(thread.getStackTrace()).willReturn(new StackTraceElement[] { element });
|
||||
given(thread.getContextClassLoader()).willReturn(classLoader);
|
||||
assertThat(initializer.getInitialUrls(thread)).isEqualTo(null);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -53,21 +53,18 @@ public class MainMethodTests {
|
||||
public void validMainMethod() throws Exception {
|
||||
MainMethod method = new TestThread(Valid::main).test();
|
||||
assertThat(method.getMethod()).isEqualTo(this.actualMain);
|
||||
assertThat(method.getDeclaringClassName())
|
||||
.isEqualTo(this.actualMain.getDeclaringClass().getName());
|
||||
assertThat(method.getDeclaringClassName()).isEqualTo(this.actualMain.getDeclaringClass().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingArgsMainMethod() throws Exception {
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> new TestThread(MissingArgs::main).test())
|
||||
assertThatIllegalStateException().isThrownBy(() -> new TestThread(MissingArgs::main).test())
|
||||
.withMessageContaining("Unable to find main method");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonStatic() throws Exception {
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> new TestThread(() -> new NonStaticMain().main()).test())
|
||||
assertThatIllegalStateException().isThrownBy(() -> new TestThread(() -> new NonStaticMain().main()).test())
|
||||
.withMessageContaining("Unable to find main method");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -60,17 +60,16 @@ public class MockRestarter implements TestRule {
|
||||
private void setup() {
|
||||
Restarter.setInstance(this.mock);
|
||||
given(this.mock.getInitialUrls()).willReturn(new URL[] {});
|
||||
given(this.mock.getOrAddAttribute(anyString(), any(ObjectFactory.class)))
|
||||
.willAnswer((invocation) -> {
|
||||
String name = invocation.getArgument(0);
|
||||
ObjectFactory factory = invocation.getArgument(1);
|
||||
Object attribute = MockRestarter.this.attributes.get(name);
|
||||
if (attribute == null) {
|
||||
attribute = factory.getObject();
|
||||
MockRestarter.this.attributes.put(name, attribute);
|
||||
}
|
||||
return attribute;
|
||||
});
|
||||
given(this.mock.getOrAddAttribute(anyString(), any(ObjectFactory.class))).willAnswer((invocation) -> {
|
||||
String name = invocation.getArgument(0);
|
||||
ObjectFactory factory = invocation.getArgument(1);
|
||||
Object attribute = MockRestarter.this.attributes.get(name);
|
||||
if (attribute == null) {
|
||||
attribute = factory.getObject();
|
||||
MockRestarter.this.attributes.put(name, attribute);
|
||||
}
|
||||
return attribute;
|
||||
});
|
||||
given(this.mock.getThreadFactory()).willReturn(Thread::new);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -50,8 +50,7 @@ public class OnInitializedRestarterConditionTests {
|
||||
@Test
|
||||
public void noInstance() {
|
||||
Restarter.clearInstance();
|
||||
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
Config.class);
|
||||
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
|
||||
assertThat(context.containsBean("bean")).isFalse();
|
||||
context.close();
|
||||
}
|
||||
@@ -59,8 +58,7 @@ public class OnInitializedRestarterConditionTests {
|
||||
@Test
|
||||
public void noInitialization() {
|
||||
Restarter.initialize(new String[0], false, RestartInitializer.NONE);
|
||||
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
Config.class);
|
||||
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
|
||||
assertThat(context.containsBean("bean")).isFalse();
|
||||
context.close();
|
||||
}
|
||||
@@ -80,8 +78,7 @@ public class OnInitializedRestarterConditionTests {
|
||||
RestartInitializer initializer = mock(RestartInitializer.class);
|
||||
given(initializer.getInitialUrls(any(Thread.class))).willReturn(new URL[0]);
|
||||
Restarter.initialize(new String[0], false, initializer);
|
||||
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
Config.class);
|
||||
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
|
||||
assertThat(context.containsBean("bean")).isTrue();
|
||||
context.close();
|
||||
synchronized (wait) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -61,8 +61,7 @@ public class RestartApplicationListenerTests {
|
||||
|
||||
@Test
|
||||
public void isHighestPriority() {
|
||||
assertThat(new RestartApplicationListener().getOrder())
|
||||
.isEqualTo(Ordered.HIGHEST_PRECEDENCE);
|
||||
assertThat(new RestartApplicationListener().getOrder()).isEqualTo(Ordered.HIGHEST_PRECEDENCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -70,8 +69,7 @@ public class RestartApplicationListenerTests {
|
||||
testInitialize(false);
|
||||
assertThat(Restarter.getInstance()).hasFieldOrPropertyWithValue("args", ARGS);
|
||||
assertThat(Restarter.getInstance().isFinished()).isTrue();
|
||||
assertThat((List<?>) ReflectionTestUtils.getField(Restarter.getInstance(),
|
||||
"rootContexts")).isNotEmpty();
|
||||
assertThat((List<?>) ReflectionTestUtils.getField(Restarter.getInstance(), "rootContexts")).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -79,8 +77,7 @@ public class RestartApplicationListenerTests {
|
||||
testInitialize(true);
|
||||
assertThat(Restarter.getInstance()).hasFieldOrPropertyWithValue("args", ARGS);
|
||||
assertThat(Restarter.getInstance().isFinished()).isTrue();
|
||||
assertThat((List<?>) ReflectionTestUtils.getField(Restarter.getInstance(),
|
||||
"rootContexts")).isEmpty();
|
||||
assertThat((List<?>) ReflectionTestUtils.getField(Restarter.getInstance(), "rootContexts")).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -89,28 +86,23 @@ public class RestartApplicationListenerTests {
|
||||
this.output.reset();
|
||||
testInitialize(false);
|
||||
assertThat(Restarter.getInstance()).hasFieldOrPropertyWithValue("enabled", false);
|
||||
assertThat(this.output.toString())
|
||||
.contains("Restart disabled due to System property");
|
||||
assertThat(this.output.toString()).contains("Restart disabled due to System property");
|
||||
}
|
||||
|
||||
private void testInitialize(boolean failed) {
|
||||
Restarter.clearInstance();
|
||||
RestartApplicationListener listener = new RestartApplicationListener();
|
||||
SpringApplication application = new SpringApplication();
|
||||
ConfigurableApplicationContext context = mock(
|
||||
ConfigurableApplicationContext.class);
|
||||
ConfigurableApplicationContext context = mock(ConfigurableApplicationContext.class);
|
||||
listener.onApplicationEvent(new ApplicationStartingEvent(application, ARGS));
|
||||
assertThat(Restarter.getInstance()).isNotEqualTo(nullValue());
|
||||
assertThat(Restarter.getInstance().isFinished()).isFalse();
|
||||
listener.onApplicationEvent(
|
||||
new ApplicationPreparedEvent(application, ARGS, context));
|
||||
listener.onApplicationEvent(new ApplicationPreparedEvent(application, ARGS, context));
|
||||
if (failed) {
|
||||
listener.onApplicationEvent(new ApplicationFailedEvent(application, ARGS,
|
||||
context, new RuntimeException()));
|
||||
listener.onApplicationEvent(new ApplicationFailedEvent(application, ARGS, context, new RuntimeException()));
|
||||
}
|
||||
else {
|
||||
listener.onApplicationEvent(
|
||||
new ApplicationReadyEvent(application, ARGS, context));
|
||||
listener.onApplicationEvent(new ApplicationReadyEvent(application, ARGS, context));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -70,8 +70,7 @@ public class RestartScopeInitializerTests {
|
||||
|
||||
}
|
||||
|
||||
public static class ScopeTestBean
|
||||
implements ApplicationListener<ContextRefreshedEvent> {
|
||||
public static class ScopeTestBean implements ApplicationListener<ContextRefreshedEvent> {
|
||||
|
||||
public ScopeTestBean() {
|
||||
createCount.incrementAndGet();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -100,8 +100,7 @@ public class RestarterTests {
|
||||
|
||||
@Test
|
||||
public void addUrlsMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> Restarter.getInstance().addUrls(null))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> Restarter.getInstance().addUrls(null))
|
||||
.withMessageContaining("Urls must not be null");
|
||||
}
|
||||
|
||||
@@ -112,15 +111,13 @@ public class RestarterTests {
|
||||
Restarter restarter = Restarter.getInstance();
|
||||
restarter.addUrls(urls);
|
||||
restarter.restart();
|
||||
ClassLoader classLoader = ((TestableRestarter) restarter)
|
||||
.getRelaunchClassLoader();
|
||||
ClassLoader classLoader = ((TestableRestarter) restarter).getRelaunchClassLoader();
|
||||
assertThat(((URLClassLoader) classLoader).getURLs()[0]).isEqualTo(url);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addClassLoaderFilesMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> Restarter.getInstance().addClassLoaderFiles(null))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> Restarter.getInstance().addClassLoaderFiles(null))
|
||||
.withMessageContaining("ClassLoaderFiles must not be null");
|
||||
}
|
||||
|
||||
@@ -131,10 +128,8 @@ public class RestarterTests {
|
||||
Restarter restarter = Restarter.getInstance();
|
||||
restarter.addClassLoaderFiles(classLoaderFiles);
|
||||
restarter.restart();
|
||||
ClassLoader classLoader = ((TestableRestarter) restarter)
|
||||
.getRelaunchClassLoader();
|
||||
assertThat(FileCopyUtils.copyToByteArray(classLoader.getResourceAsStream("f")))
|
||||
.isEqualTo("abc".getBytes());
|
||||
ClassLoader classLoader = ((TestableRestarter) restarter).getRelaunchClassLoader();
|
||||
assertThat(FileCopyUtils.copyToByteArray(classLoader.getResourceAsStream("f"))).isEqualTo("abc".getBytes());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -219,8 +214,7 @@ public class RestarterTests {
|
||||
|
||||
}
|
||||
|
||||
private static class CloseCountingApplicationListener
|
||||
implements ApplicationListener<ContextClosedEvent> {
|
||||
private static class CloseCountingApplicationListener implements ApplicationListener<ContextClosedEvent> {
|
||||
|
||||
static int closed = 0;
|
||||
|
||||
@@ -236,12 +230,11 @@ public class RestarterTests {
|
||||
private ClassLoader relaunchClassLoader;
|
||||
|
||||
TestableRestarter() {
|
||||
this(Thread.currentThread(), new String[] {}, false,
|
||||
new MockRestartInitializer());
|
||||
this(Thread.currentThread(), new String[] {}, false, new MockRestartInitializer());
|
||||
}
|
||||
|
||||
protected TestableRestarter(Thread thread, String[] args,
|
||||
boolean forceReferenceCleanup, RestartInitializer initializer) {
|
||||
protected TestableRestarter(Thread thread, String[] args, boolean forceReferenceCleanup,
|
||||
RestartInitializer initializer) {
|
||||
super(thread, args, forceReferenceCleanup, initializer);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -81,8 +81,7 @@ public class SilentExitExceptionHandlerTests {
|
||||
private Throwable thrown;
|
||||
|
||||
TestThread() {
|
||||
setUncaughtExceptionHandler(
|
||||
(thread, exception) -> TestThread.this.thrown = exception);
|
||||
setUncaughtExceptionHandler((thread, exception) -> TestThread.this.thrown = exception);
|
||||
}
|
||||
|
||||
public Throwable getThrown() {
|
||||
@@ -96,8 +95,7 @@ public class SilentExitExceptionHandlerTests {
|
||||
|
||||
}
|
||||
|
||||
private static class TestSilentExitExceptionHandler
|
||||
extends SilentExitExceptionHandler {
|
||||
private static class TestSilentExitExceptionHandler extends SilentExitExceptionHandler {
|
||||
|
||||
private boolean nonZeroExitCodePrevented;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -34,29 +34,25 @@ public class ClassLoaderFileTests {
|
||||
|
||||
@Test
|
||||
public void kindMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new ClassLoaderFile(null, null))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new ClassLoaderFile(null, null))
|
||||
.withMessageContaining("Kind must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addedContentsMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new ClassLoaderFile(Kind.ADDED, null))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new ClassLoaderFile(Kind.ADDED, null))
|
||||
.withMessageContaining("Contents must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void modifiedContentsMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new ClassLoaderFile(Kind.MODIFIED, null))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new ClassLoaderFile(Kind.MODIFIED, null))
|
||||
.withMessageContaining("Contents must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deletedContentsMustBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new ClassLoaderFile(Kind.DELETED, new byte[10]))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new ClassLoaderFile(Kind.DELETED, new byte[10]))
|
||||
.withMessageContaining("Contents must be null");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -42,15 +42,13 @@ public class ClassLoaderFilesTests {
|
||||
|
||||
@Test
|
||||
public void addFileNameMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> this.files.addFile(null, mock(ClassLoaderFile.class)))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.files.addFile(null, mock(ClassLoaderFile.class)))
|
||||
.withMessageContaining("Name must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addFileFileMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> this.files.addFile("test", null))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.files.addFile("test", null))
|
||||
.withMessageContaining("File must not be null");
|
||||
}
|
||||
|
||||
@@ -87,10 +85,8 @@ public class ClassLoaderFilesTests {
|
||||
this.files.addFile("a", "myfile", file1);
|
||||
this.files.addFile("b", "myfile", file2);
|
||||
assertThat(this.files.getFile("myfile")).isEqualTo(file2);
|
||||
assertThat(this.files.getOrCreateSourceFolder("a").getFiles().size())
|
||||
.isEqualTo(0);
|
||||
assertThat(this.files.getOrCreateSourceFolder("b").getFiles().size())
|
||||
.isEqualTo(1);
|
||||
assertThat(this.files.getOrCreateSourceFolder("a").getFiles().size()).isEqualTo(0);
|
||||
assertThat(this.files.getOrCreateSourceFolder("b").getFiles().size()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -121,8 +117,7 @@ public class ClassLoaderFilesTests {
|
||||
ObjectOutputStream oos = new ObjectOutputStream(bos);
|
||||
oos.writeObject(this.files);
|
||||
oos.close();
|
||||
ObjectInputStream ois = new ObjectInputStream(
|
||||
new ByteArrayInputStream(bos.toByteArray()));
|
||||
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
|
||||
ClassLoaderFiles readObject = (ClassLoaderFiles) ois.readObject();
|
||||
assertThat(readObject.getFile("myfile")).isNotNull();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -50,8 +50,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||
@SuppressWarnings("resource")
|
||||
public class RestartClassLoaderTests {
|
||||
|
||||
private static final String PACKAGE = RestartClassLoaderTests.class.getPackage()
|
||||
.getName();
|
||||
private static final String PACKAGE = RestartClassLoaderTests.class.getPackage().getName();
|
||||
|
||||
private static final String PACKAGE_PATH = PACKAGE.replace('.', '/');
|
||||
|
||||
@@ -74,8 +73,7 @@ public class RestartClassLoaderTests {
|
||||
URL[] urls = new URL[] { url };
|
||||
this.parentClassLoader = new URLClassLoader(urls, classLoader);
|
||||
this.updatedFiles = new ClassLoaderFiles();
|
||||
this.reloadClassLoader = new RestartClassLoader(this.parentClassLoader, urls,
|
||||
this.updatedFiles);
|
||||
this.reloadClassLoader = new RestartClassLoader(this.parentClassLoader, urls, this.updatedFiles);
|
||||
}
|
||||
|
||||
private File createSampleJarFile() throws IOException {
|
||||
@@ -93,36 +91,32 @@ public class RestartClassLoaderTests {
|
||||
|
||||
@Test
|
||||
public void parentMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new RestartClassLoader(null, new URL[] {}))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new RestartClassLoader(null, new URL[] {}))
|
||||
.withMessageContaining("Parent must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updatedFilesMustNotBeNull() {
|
||||
assertThatIllegalArgumentException().isThrownBy(
|
||||
() -> new RestartClassLoader(this.parentClassLoader, new URL[] {}, null))
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new RestartClassLoader(this.parentClassLoader, new URL[] {}, null))
|
||||
.withMessageContaining("UpdatedFiles must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getResourceFromReloadableUrl() throws Exception {
|
||||
String content = readString(
|
||||
this.reloadClassLoader.getResourceAsStream(PACKAGE_PATH + "/Sample.txt"));
|
||||
String content = readString(this.reloadClassLoader.getResourceAsStream(PACKAGE_PATH + "/Sample.txt"));
|
||||
assertThat(content).startsWith("fromchild");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getResourceFromParent() throws Exception {
|
||||
String content = readString(
|
||||
this.reloadClassLoader.getResourceAsStream(PACKAGE_PATH + "/Parent.txt"));
|
||||
String content = readString(this.reloadClassLoader.getResourceAsStream(PACKAGE_PATH + "/Parent.txt"));
|
||||
assertThat(content).startsWith("fromparent");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getResourcesFiltersDuplicates() throws Exception {
|
||||
List<URL> resources = toList(
|
||||
this.reloadClassLoader.getResources(PACKAGE_PATH + "/Sample.txt"));
|
||||
List<URL> resources = toList(this.reloadClassLoader.getResources(PACKAGE_PATH + "/Sample.txt"));
|
||||
assertThat(resources.size()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@@ -175,8 +169,7 @@ public class RestartClassLoaderTests {
|
||||
byte[] bytes = "abc".getBytes();
|
||||
this.updatedFiles.addFile(name, new ClassLoaderFile(Kind.MODIFIED, bytes));
|
||||
List<URL> resources = toList(this.reloadClassLoader.getResources(name));
|
||||
assertThat(FileCopyUtils.copyToByteArray(resources.get(0).openStream()))
|
||||
.isEqualTo(bytes);
|
||||
assertThat(FileCopyUtils.copyToByteArray(resources.get(0).openStream())).isEqualTo(bytes);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -198,8 +191,7 @@ public class RestartClassLoaderTests {
|
||||
@Test
|
||||
public void getAddedClass() throws Exception {
|
||||
String name = PACKAGE_PATH + "/SampleParent.class";
|
||||
byte[] bytes = FileCopyUtils
|
||||
.copyToByteArray(getClass().getResourceAsStream("SampleParent.class"));
|
||||
byte[] bytes = FileCopyUtils.copyToByteArray(getClass().getResourceAsStream("SampleParent.class"));
|
||||
this.updatedFiles.addFile(name, new ClassLoaderFile(Kind.ADDED, bytes));
|
||||
Class<?> loaded = this.reloadClassLoader.loadClass(PACKAGE + ".SampleParent");
|
||||
assertThat(loaded.getClassLoader()).isEqualTo(this.reloadClassLoader);
|
||||
@@ -210,8 +202,7 @@ public class RestartClassLoaderTests {
|
||||
}
|
||||
|
||||
private <T> List<T> toList(Enumeration<T> enumeration) {
|
||||
return (enumeration != null) ? Collections.list(enumeration)
|
||||
: Collections.emptyList();
|
||||
return (enumeration != null) ? Collections.list(enumeration) : Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -71,17 +71,13 @@ public class DefaultSourceFolderUrlFilterTests {
|
||||
|
||||
@Test
|
||||
public void skippedProjects() throws Exception {
|
||||
String sourceFolder = "/Users/me/code/spring-boot-samples/"
|
||||
+ "spring-boot-sample-devtools";
|
||||
URL jarUrl = new URL("jar:file:/Users/me/tmp/"
|
||||
+ "spring-boot-sample-devtools-1.3.0.BUILD-SNAPSHOT.jar!/");
|
||||
String sourceFolder = "/Users/me/code/spring-boot-samples/" + "spring-boot-sample-devtools";
|
||||
URL jarUrl = new URL("jar:file:/Users/me/tmp/" + "spring-boot-sample-devtools-1.3.0.BUILD-SNAPSHOT.jar!/");
|
||||
assertThat(this.filter.isMatch(sourceFolder, jarUrl)).isTrue();
|
||||
URL nestedJarUrl = new URL("jar:file:/Users/me/tmp/"
|
||||
+ "spring-boot-sample-devtools-1.3.0.BUILD-SNAPSHOT.jar!/"
|
||||
URL nestedJarUrl = new URL("jar:file:/Users/me/tmp/" + "spring-boot-sample-devtools-1.3.0.BUILD-SNAPSHOT.jar!/"
|
||||
+ "lib/spring-boot-1.3.0.BUILD-SNAPSHOT.jar!/");
|
||||
assertThat(this.filter.isMatch(sourceFolder, nestedJarUrl)).isFalse();
|
||||
URL fileUrl = new URL("file:/Users/me/tmp/"
|
||||
+ "spring-boot-sample-devtools-1.3.0.BUILD-SNAPSHOT.jar");
|
||||
URL fileUrl = new URL("file:/Users/me/tmp/" + "spring-boot-sample-devtools-1.3.0.BUILD-SNAPSHOT.jar");
|
||||
assertThat(this.filter.isMatch(sourceFolder, fileUrl)).isTrue();
|
||||
}
|
||||
|
||||
@@ -92,14 +88,12 @@ public class DefaultSourceFolderUrlFilterTests {
|
||||
doTest(sourcePostfix, "my-module.other", false);
|
||||
}
|
||||
|
||||
private void doTest(String sourcePostfix, String moduleRoot, boolean expected)
|
||||
throws MalformedURLException {
|
||||
private void doTest(String sourcePostfix, String moduleRoot, boolean expected) throws MalformedURLException {
|
||||
String sourceFolder = SOURCE_ROOT + sourcePostfix;
|
||||
for (String postfix : COMMON_POSTFIXES) {
|
||||
for (URL url : getUrls(moduleRoot + postfix)) {
|
||||
boolean match = this.filter.isMatch(sourceFolder, url);
|
||||
assertThat(match).as(url + " against " + sourceFolder)
|
||||
.isEqualTo(expected);
|
||||
assertThat(match).as(url + " against " + sourceFolder).isEqualTo(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,10 +103,8 @@ public class DefaultSourceFolderUrlFilterTests {
|
||||
urls.add(new URL("file:/some/path/" + name));
|
||||
urls.add(new URL("file:/some/path/" + name + "!/"));
|
||||
for (String postfix : COMMON_POSTFIXES) {
|
||||
urls.add(new URL(
|
||||
"jar:file:/some/path/lib-module" + postfix + "!/lib/" + name));
|
||||
urls.add(new URL(
|
||||
"jar:file:/some/path/lib-module" + postfix + "!/lib/" + name + "!/"));
|
||||
urls.add(new URL("jar:file:/some/path/lib-module" + postfix + "!/lib/" + name));
|
||||
urls.add(new URL("jar:file:/some/path/lib-module" + postfix + "!/lib/" + name + "!/"));
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -34,8 +34,7 @@ public class HttpRestartServerHandlerTests {
|
||||
|
||||
@Test
|
||||
public void serverMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new HttpRestartServerHandler(null))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new HttpRestartServerHandler(null))
|
||||
.withMessageContaining("Server must not be null");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -63,15 +63,13 @@ public class HttpRestartServerTests {
|
||||
|
||||
@Test
|
||||
public void sourceFolderUrlFilterMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new HttpRestartServer((SourceFolderUrlFilter) null))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new HttpRestartServer((SourceFolderUrlFilter) null))
|
||||
.withMessageContaining("SourceFolderUrlFilter must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restartServerMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new HttpRestartServer((RestartServer) null))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new HttpRestartServer((RestartServer) null))
|
||||
.withMessageContaining("RestartServer must not be null");
|
||||
}
|
||||
|
||||
@@ -83,8 +81,7 @@ public class HttpRestartServerTests {
|
||||
files.addFile("name", new ClassLoaderFile(Kind.ADDED, new byte[0]));
|
||||
byte[] bytes = serialize(files);
|
||||
request.setContent(bytes);
|
||||
this.server.handle(new ServletServerHttpRequest(request),
|
||||
new ServletServerHttpResponse(response));
|
||||
this.server.handle(new ServletServerHttpRequest(request), new ServletServerHttpResponse(response));
|
||||
verify(this.delegate).updateAndRestart(this.filesCaptor.capture());
|
||||
assertThat(this.filesCaptor.getValue().getFile("name")).isNotNull();
|
||||
assertThat(response.getStatus()).isEqualTo(200);
|
||||
@@ -94,8 +91,7 @@ public class HttpRestartServerTests {
|
||||
public void sendNoContent() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
this.server.handle(new ServletServerHttpRequest(request),
|
||||
new ServletServerHttpResponse(response));
|
||||
this.server.handle(new ServletServerHttpRequest(request), new ServletServerHttpResponse(response));
|
||||
verifyZeroInteractions(this.delegate);
|
||||
assertThat(response.getStatus()).isEqualTo(500);
|
||||
|
||||
@@ -106,8 +102,7 @@ public class HttpRestartServerTests {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
request.setContent(new byte[] { 0, 0, 0 });
|
||||
this.server.handle(new ServletServerHttpRequest(request),
|
||||
new ServletServerHttpResponse(response));
|
||||
this.server.handle(new ServletServerHttpRequest(request), new ServletServerHttpResponse(response));
|
||||
verifyZeroInteractions(this.delegate);
|
||||
assertThat(response.getStatus()).isEqualTo(500);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
* Copyright 2012-2019 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.
|
||||
@@ -48,8 +48,7 @@ public class RestartServerTests {
|
||||
|
||||
@Test
|
||||
public void sourceFolderUrlFilterMustNotBeNull() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new RestartServer((SourceFolderUrlFilter) null))
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new RestartServer((SourceFolderUrlFilter) null))
|
||||
.withMessageContaining("SourceFolderUrlFilter must not be null");
|
||||
}
|
||||
|
||||
@@ -60,8 +59,7 @@ public class RestartServerTests {
|
||||
URL url3 = new URL("file:/proj/module-c.jar!/");
|
||||
URL url4 = new URL("file:/proj/module-d.jar!/");
|
||||
URLClassLoader classLoaderA = new URLClassLoader(new URL[] { url1, url2 });
|
||||
URLClassLoader classLoaderB = new URLClassLoader(new URL[] { url3, url4 },
|
||||
classLoaderA);
|
||||
URLClassLoader classLoaderB = new URLClassLoader(new URL[] { url3, url4 }, classLoaderA);
|
||||
SourceFolderUrlFilter filter = new DefaultSourceFolderUrlFilter();
|
||||
MockRestartServer server = new MockRestartServer(filter, classLoaderB);
|
||||
ClassLoaderFiles files = new ClassLoaderFiles();
|
||||
@@ -114,8 +112,7 @@ public class RestartServerTests {
|
||||
|
||||
private static class MockRestartServer extends RestartServer {
|
||||
|
||||
MockRestartServer(SourceFolderUrlFilter sourceFolderUrlFilter,
|
||||
ClassLoader classLoader) {
|
||||
MockRestartServer(SourceFolderUrlFilter sourceFolderUrlFilter, ClassLoader classLoader) {
|
||||
super(sourceFolderUrlFilter, classLoader);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user