Merge branch '2.1.x'

Closes gh-18239
pull/18244/head
Stephane Nicoll 5 years ago
commit 81ddebbc27

@ -22,8 +22,10 @@ import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;
import java.util.function.Supplier;
import org.springframework.boot.devtools.restart.classloader.ClassLoaderFile;
import org.springframework.boot.devtools.restart.classloader.ClassLoaderFile.Kind;
@ -31,6 +33,7 @@ import org.springframework.boot.devtools.restart.classloader.ClassLoaderFileURLS
import org.springframework.boot.devtools.restart.classloader.ClassLoaderFiles;
import org.springframework.boot.devtools.restart.classloader.ClassLoaderFiles.SourceFolder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.core.io.AbstractResource;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ProtocolResolver;
@ -67,7 +70,8 @@ final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternRe
private final ClassLoaderFiles classLoaderFiles;
ClassLoaderFilesResourcePatternResolver(ApplicationContext applicationContext, ClassLoaderFiles classLoaderFiles) {
ClassLoaderFilesResourcePatternResolver(AbstractApplicationContext applicationContext,
ClassLoaderFiles classLoaderFiles) {
this.classLoaderFiles = classLoaderFiles;
this.patternResolverDelegate = getResourcePatternResolverFactory()
.getResourcePatternResolver(applicationContext, retrieveResourceLoader(applicationContext));
@ -195,28 +199,11 @@ final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternRe
*/
private static class ResourcePatternResolverFactory {
ResourcePatternResolver getResourcePatternResolver(ApplicationContext applicationContext,
ResourcePatternResolver getResourcePatternResolver(AbstractApplicationContext applicationContext,
ResourceLoader resourceLoader) {
if (resourceLoader == null) {
resourceLoader = new DefaultResourceLoader();
copyProtocolResolvers(applicationContext, resourceLoader);
}
return new PathMatchingResourcePatternResolver(resourceLoader);
}
protected final void copyProtocolResolvers(ApplicationContext applicationContext,
ResourceLoader resourceLoader) {
if (applicationContext instanceof DefaultResourceLoader
&& resourceLoader instanceof DefaultResourceLoader) {
copyProtocolResolvers((DefaultResourceLoader) applicationContext,
(DefaultResourceLoader) resourceLoader);
}
}
protected final void copyProtocolResolvers(DefaultResourceLoader source, DefaultResourceLoader destination) {
for (ProtocolResolver resolver : source.getProtocolResolvers()) {
destination.addProtocolResolver(resolver);
}
ResourceLoader targetResourceLoader = (resourceLoader != null) ? resourceLoader
: new ApplicationContextResourceLoader(applicationContext::getProtocolResolvers);
return new PathMatchingResourcePatternResolver(targetResourceLoader);
}
}
@ -228,21 +215,35 @@ final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternRe
private static class WebResourcePatternResolverFactory extends ResourcePatternResolverFactory {
@Override
public ResourcePatternResolver getResourcePatternResolver(ApplicationContext applicationContext,
public ResourcePatternResolver getResourcePatternResolver(AbstractApplicationContext applicationContext,
ResourceLoader resourceLoader) {
if (applicationContext instanceof WebApplicationContext) {
return getResourcePatternResolver((WebApplicationContext) applicationContext, resourceLoader);
return getServletContextResourcePatternResolver(applicationContext, resourceLoader);
}
return super.getResourcePatternResolver(applicationContext, resourceLoader);
}
private ResourcePatternResolver getResourcePatternResolver(WebApplicationContext applicationContext,
ResourceLoader resourceLoader) {
if (resourceLoader == null) {
resourceLoader = new WebApplicationContextResourceLoader(applicationContext);
copyProtocolResolvers(applicationContext, resourceLoader);
}
return new ServletContextResourcePatternResolver(resourceLoader);
private ResourcePatternResolver getServletContextResourcePatternResolver(
AbstractApplicationContext applicationContext, ResourceLoader resourceLoader) {
ResourceLoader targetResourceLoader = (resourceLoader != null) ? resourceLoader
: new WebApplicationContextResourceLoader(applicationContext::getProtocolResolvers,
(WebApplicationContext) applicationContext);
return new ServletContextResourcePatternResolver(targetResourceLoader);
}
}
private static class ApplicationContextResourceLoader extends DefaultResourceLoader {
private final Supplier<Collection<ProtocolResolver>> protocolResolvers;
ApplicationContextResourceLoader(Supplier<Collection<ProtocolResolver>> protocolResolvers) {
this.protocolResolvers = protocolResolvers;
}
@Override
public Collection<ProtocolResolver> getProtocolResolvers() {
return this.protocolResolvers.get();
}
}
@ -251,11 +252,13 @@ final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternRe
* {@link ResourceLoader} that optionally supports {@link ServletContextResource
* ServletContextResources}.
*/
private static class WebApplicationContextResourceLoader extends DefaultResourceLoader {
private static class WebApplicationContextResourceLoader extends ApplicationContextResourceLoader {
private final WebApplicationContext applicationContext;
WebApplicationContextResourceLoader(WebApplicationContext applicationContext) {
WebApplicationContextResourceLoader(Supplier<Collection<ProtocolResolver>> protocolResolvers,
WebApplicationContext applicationContext) {
super(protocolResolvers);
this.applicationContext = applicationContext;
}

@ -127,6 +127,18 @@ class ClassLoaderFilesResourcePatternResolverTests {
verify(resolver).resolve(eq("foo:some-file.txt"), any(ResourceLoader.class));
}
@Test
void customProtocolResolverRegisteredAfterCreationIsUsedInNonWebApplication() {
GenericApplicationContext context = new GenericApplicationContext();
Resource resource = mock(Resource.class);
this.resolver = new ClassLoaderFilesResourcePatternResolver(context, this.files);
ProtocolResolver resolver = mockProtocolResolver("foo:some-file.txt", resource);
context.addProtocolResolver(resolver);
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
void customResourceLoaderIsUsedInWebApplication() {
GenericWebApplicationContext context = new GenericWebApplicationContext(new MockServletContext());
@ -149,6 +161,18 @@ class ClassLoaderFilesResourcePatternResolverTests {
verify(resolver).resolve(eq("foo:some-file.txt"), any(ResourceLoader.class));
}
@Test
void customProtocolResolverRegisteredAfterCreationIsUsedInWebApplication() {
GenericWebApplicationContext context = new GenericWebApplicationContext(new MockServletContext());
Resource resource = mock(Resource.class);
this.resolver = new ClassLoaderFilesResourcePatternResolver(context, this.files);
ProtocolResolver resolver = mockProtocolResolver("foo:some-file.txt", resource);
context.addProtocolResolver(resolver);
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);

Loading…
Cancel
Save