Commit 05fbd5dc authored by Stephane Nicoll's avatar Stephane Nicoll

Merge branch '1.5.x'

parents d844a0cf cbdab9ed
...@@ -22,6 +22,7 @@ import java.lang.reflect.Field; ...@@ -22,6 +22,7 @@ import java.lang.reflect.Field;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
...@@ -33,6 +34,7 @@ import org.springframework.boot.devtools.restart.classloader.ClassLoaderFiles.So ...@@ -33,6 +34,7 @@ import org.springframework.boot.devtools.restart.classloader.ClassLoaderFiles.So
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.core.io.AbstractResource; import org.springframework.core.io.AbstractResource;
import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ProtocolResolver;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.UrlResource; import org.springframework.core.io.UrlResource;
...@@ -52,6 +54,7 @@ import org.springframework.web.context.support.ServletContextResourcePatternReso ...@@ -52,6 +54,7 @@ import org.springframework.web.context.support.ServletContextResourcePatternReso
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Phillip Webb * @author Phillip Webb
* @author Stephane Nicoll
*/ */
final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternResolver { final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternResolver {
...@@ -206,7 +209,20 @@ final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternRe ...@@ -206,7 +209,20 @@ final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternRe
public ResourcePatternResolver getResourcePatternResolver( public ResourcePatternResolver getResourcePatternResolver(
ApplicationContext applicationContext, ResourceLoader resourceLoader) { ApplicationContext applicationContext, ResourceLoader resourceLoader) {
return new PathMatchingResourcePatternResolver(resourceLoader == null return new PathMatchingResourcePatternResolver(resourceLoader == null
? new DefaultResourceLoader() : resourceLoader); ? createResourceLoader(applicationContext) : resourceLoader);
}
private ResourceLoader createResourceLoader(
ApplicationContext applicationContext) {
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
if (applicationContext instanceof DefaultResourceLoader) {
Collection<ProtocolResolver> protocolResolvers =
((DefaultResourceLoader) applicationContext).getProtocolResolvers();
for (ProtocolResolver protocolResolver : protocolResolvers) {
resourceLoader.addProtocolResolver(protocolResolver);
}
}
return resourceLoader;
} }
} }
...@@ -223,13 +239,26 @@ final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternRe ...@@ -223,13 +239,26 @@ final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternRe
ApplicationContext applicationContext, ResourceLoader resourceLoader) { ApplicationContext applicationContext, ResourceLoader resourceLoader) {
if (applicationContext instanceof WebApplicationContext) { if (applicationContext instanceof WebApplicationContext) {
return new ServletContextResourcePatternResolver(resourceLoader == null return new ServletContextResourcePatternResolver(resourceLoader == null
? new WebApplicationContextResourceLoader( ? createResourceLoader((WebApplicationContext) applicationContext)
(WebApplicationContext) applicationContext)
: resourceLoader); : resourceLoader);
} }
return super.getResourcePatternResolver(applicationContext, resourceLoader); return super.getResourcePatternResolver(applicationContext, resourceLoader);
} }
private ResourceLoader createResourceLoader(
WebApplicationContext applicationContext) {
WebApplicationContextResourceLoader resourceLoader =
new WebApplicationContextResourceLoader(applicationContext);
if (applicationContext instanceof DefaultResourceLoader) {
Collection<ProtocolResolver> protocolResolvers =
((DefaultResourceLoader) applicationContext).getProtocolResolvers();
for (ProtocolResolver protocolResolver : protocolResolvers) {
resourceLoader.addProtocolResolver(protocolResolver);
}
}
return resourceLoader;
}
} }
/** /**
......
...@@ -30,6 +30,7 @@ import org.springframework.boot.devtools.restart.classloader.ClassLoaderFile.Kin ...@@ -30,6 +30,7 @@ import org.springframework.boot.devtools.restart.classloader.ClassLoaderFile.Kin
import org.springframework.boot.devtools.restart.classloader.ClassLoaderFiles; import org.springframework.boot.devtools.restart.classloader.ClassLoaderFiles;
import org.springframework.context.support.GenericApplicationContext; import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.ProtocolResolver;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.springframework.mock.web.MockServletContext; import org.springframework.mock.web.MockServletContext;
...@@ -38,6 +39,9 @@ import org.springframework.web.context.support.GenericWebApplicationContext; ...@@ -38,6 +39,9 @@ import org.springframework.web.context.support.GenericWebApplicationContext;
import org.springframework.web.context.support.ServletContextResource; import org.springframework.web.context.support.ServletContextResource;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
...@@ -46,6 +50,7 @@ import static org.mockito.Mockito.verify; ...@@ -46,6 +50,7 @@ import static org.mockito.Mockito.verify;
* *
* @author Phillip Webb * @author Phillip Webb
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Stephane Nicoll
*/ */
public class ClassLoaderFilesResourcePatternResolverTests { public class ClassLoaderFilesResourcePatternResolverTests {
...@@ -125,6 +130,18 @@ public class ClassLoaderFilesResourcePatternResolverTests { ...@@ -125,6 +130,18 @@ public class ClassLoaderFilesResourcePatternResolverTests {
verify(resourceLoader).getResource("foo.txt"); verify(resourceLoader).getResource("foo.txt");
} }
@Test
public void customProtocolResolverIsUsedInNonWebApplication() throws Exception {
GenericApplicationContext context = new GenericApplicationContext();
Resource resource = mock(Resource.class);
ProtocolResolver resolver = mockProtocolResolver("foo:some-file.txt", resource);
context.addProtocolResolver(resolver);
this.resolver = new ClassLoaderFilesResourcePatternResolver(context, this.files);
Resource actual = this.resolver.getResource("foo:some-file.txt");
assertThat(actual).isSameAs(resource);
verify(resolver).resolve(eq("foo:some-file.txt"), any(ResourceLoader.class));
}
@Test @Test
public void customResourceLoaderIsUsedInWebApplication() throws Exception { public void customResourceLoaderIsUsedInWebApplication() throws Exception {
GenericWebApplicationContext context = new GenericWebApplicationContext( GenericWebApplicationContext context = new GenericWebApplicationContext(
...@@ -136,6 +153,26 @@ public class ClassLoaderFilesResourcePatternResolverTests { ...@@ -136,6 +153,26 @@ public class ClassLoaderFilesResourcePatternResolverTests {
verify(resourceLoader).getResource("foo.txt"); verify(resourceLoader).getResource("foo.txt");
} }
@Test
public void customProtocolResolverIsUsedInWebApplication() throws Exception {
GenericWebApplicationContext context = new GenericWebApplicationContext(
new MockServletContext());
Resource resource = mock(Resource.class);
ProtocolResolver resolver = mockProtocolResolver("foo:some-file.txt", resource);
context.addProtocolResolver(resolver);
this.resolver = new ClassLoaderFilesResourcePatternResolver(context, this.files);
Resource actual = this.resolver.getResource("foo:some-file.txt");
assertThat(actual).isSameAs(resource);
verify(resolver).resolve(eq("foo:some-file.txt"), any(ResourceLoader.class));
}
private ProtocolResolver mockProtocolResolver(String path, Resource resource) {
ProtocolResolver resolver = mock(ProtocolResolver.class);
given(resolver.resolve(eq(path), any(ResourceLoader.class)))
.willReturn(resource);
return resolver;
}
private File createFile(File folder, String name) throws IOException { private File createFile(File folder, String name) throws IOException {
File file = new File(folder, name); File file = new File(folder, name);
FileCopyUtils.copy("test".getBytes(), file); FileCopyUtils.copy("test".getBytes(), file);
......
...@@ -777,6 +777,10 @@ NOTE: When deciding if an entry on the classpath should trigger a restart when i ...@@ -777,6 +777,10 @@ NOTE: When deciding if an entry on the classpath should trigger a restart when i
DevTools automatically ignores projects named `spring-boot`, `spring-boot-devtools`, DevTools automatically ignores projects named `spring-boot`, `spring-boot-devtools`,
`spring-boot-autoconfigure`, `spring-boot-actuator`, and `spring-boot-starter`. `spring-boot-autoconfigure`, `spring-boot-actuator`, and `spring-boot-starter`.
NOTE: DevTools needs to customize the `ResourceLoader` used by the `ApplicationContext`:
if your application provides one already, it is going to be wrapped. Direct override of
the `getResource` method on the `ApplicationContext` is not supported.
[[using-spring-boot-restart-vs-reload]] [[using-spring-boot-restart-vs-reload]]
.Restart vs Reload .Restart vs Reload
**** ****
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment