Skip to content

Commit

Permalink
Update ApplicationResourceLoader to support FilteredReactiveWebContex…
Browse files Browse the repository at this point in the history
…tResource

Prior to this update, FilteredReactiveWebContextResource was not
considered when preferFileResolution was set to true.

This commit updates the ApplicationResourceLoader to include support for
FilteredReactiveWebContextResource.

Signed-off-by: Dmytro Nosan <[email protected]>
  • Loading branch information
nosan committed Mar 5, 2025
1 parent d92551f commit 02498ec
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 the original author or authors.
* Copyright 2012-2025 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.
Expand Down Expand Up @@ -132,8 +132,8 @@ public static ResourceLoader get(ResourceLoader resourceLoader) {
* class loader at the time this call is made.
* @param resourceLoader the delegate resource loader
* @param preferFileResolution if file based resolution is preferred over
* {@code ServletContextResource} or {@link ClassPathResource} when no resource prefix
* is provided.
* {@code ServletContextResource}, {@code FilteredReactiveWebContextResource} or
* {@link ClassPathResource} when no resource prefix is provided.
* @return a {@link ResourceLoader} instance
* @since 3.4.1
*/
Expand Down Expand Up @@ -212,28 +212,32 @@ private static class ProtocolResolvingResourceLoader implements ResourceLoader {

private static final String SERVLET_CONTEXT_RESOURCE_CLASS_NAME = "org.springframework.web.context.support.ServletContextResource";

private static final String FILTERED_REACTIVE_WEB_CONTEXT_RESOURCE_CLASS_NAME = "org.springframework.boot.web.reactive.context.FilteredReactiveWebContextResource";

private final ResourceLoader resourceLoader;

private final List<ProtocolResolver> protocolResolvers;

private final boolean preferFileResolution;

private Class<?> servletContextResourceClass;
private final Class<?> servletContextResourceClass;

private final Class<?> filteredReactiveWebContextResourceClass;

ProtocolResolvingResourceLoader(ResourceLoader resourceLoader, List<ProtocolResolver> protocolResolvers,
boolean preferFileResolution) {
this.resourceLoader = resourceLoader;
this.protocolResolvers = protocolResolvers;
this.preferFileResolution = preferFileResolution;
this.servletContextResourceClass = resolveServletContextResourceClass(
this.servletContextResourceClass = resolveClassName(SERVLET_CONTEXT_RESOURCE_CLASS_NAME,
resourceLoader.getClass().getClassLoader());
this.filteredReactiveWebContextResourceClass = resolveClassName(
FILTERED_REACTIVE_WEB_CONTEXT_RESOURCE_CLASS_NAME, resourceLoader.getClass().getClassLoader());
}

private static Class<?> resolveServletContextResourceClass(ClassLoader classLoader) {
if (!ClassUtils.isPresent(SERVLET_CONTEXT_RESOURCE_CLASS_NAME, classLoader)) {
return null;
}
return ClassUtils.resolveClassName(SERVLET_CONTEXT_RESOURCE_CLASS_NAME, classLoader);
@Override
public ClassLoader getClassLoader() {
return this.resourceLoader.getClassLoader();
}

@Override
Expand All @@ -247,24 +251,38 @@ public Resource getResource(String location) {
}
}
Resource resource = this.resourceLoader.getResource(location);
if (this.preferFileResolution
&& (isClassPathResourceByPath(location, resource) || isServletResource(resource))) {
resource = new ApplicationResource(location);
if (shouldUseFileResolution(location, resource)) {
return new ApplicationResource(location);
}
return resource;
}

private boolean shouldUseFileResolution(String location, Resource resource) {
if (!this.preferFileResolution) {
return false;
}
return isClassPathResourceByPath(location, resource) || isServletResource(resource)
|| isFilteredReactiveWebContextResource(resource);
}

private boolean isClassPathResourceByPath(String location, Resource resource) {
return (resource instanceof ClassPathResource) && !location.startsWith(CLASSPATH_URL_PREFIX);
}

private boolean isServletResource(Resource resource) {
return this.servletContextResourceClass != null && this.servletContextResourceClass.isInstance(resource);
return (this.servletContextResourceClass != null) && this.servletContextResourceClass.isInstance(resource);
}

@Override
public ClassLoader getClassLoader() {
return this.resourceLoader.getClassLoader();
private boolean isFilteredReactiveWebContextResource(Resource resource) {
return (this.filteredReactiveWebContextResourceClass != null)
&& this.filteredReactiveWebContextResourceClass.isInstance(resource);
}

private static Class<?> resolveClassName(String clazz, ClassLoader classLoader) {
if (!ClassUtils.isPresent(clazz, classLoader)) {
return null;
}
return ClassUtils.resolveClassName(clazz, classLoader);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

import org.springframework.boot.testsupport.classpath.resources.ResourcePath;
import org.springframework.boot.testsupport.classpath.resources.WithResource;
import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebApplicationContext;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.DefaultResourceLoader;
Expand All @@ -37,6 +38,7 @@
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.mock.web.MockServletContext;
import org.springframework.util.ClassUtils;
import org.springframework.web.context.support.ServletContextResource;
import org.springframework.web.context.support.ServletContextResourceLoader;

Expand Down Expand Up @@ -209,6 +211,25 @@ void getResourceWithPreferFileResolutionWhenPathWithServletContextResource() thr
assertThat(regularLoader.getResource("src/main/resources/a-file")).isInstanceOf(ServletContextResource.class);
}

@Test
void getResourceWhenFilteredReactiveWebContextResourceWithPreferFileResolution() throws Exception {
ResourceLoader resourceLoader = ApplicationResourceLoader
.get(new AnnotationConfigReactiveWebApplicationContext(), true);
Resource resource = resourceLoader.getResource("src/main/resources/a-file");
assertThat(resource).isInstanceOf(FileSystemResource.class);
assertThat(resource.getFile().getAbsoluteFile())
.isEqualTo(new File("src/main/resources/a-file").getAbsoluteFile());
}

@Test
void getResourceWhenFilteredReactiveWebContextResource() {
ResourceLoader resourceLoader = ApplicationResourceLoader
.get(new AnnotationConfigReactiveWebApplicationContext(), false);
Resource resource = resourceLoader.getResource("src/main/resources/a-file");
assertThat(resource).isInstanceOf(ClassUtils.resolveClassName(
"org.springframework.boot.web.reactive.context.FilteredReactiveWebContextResource", null));
}

@Test
void getClassLoaderReturnsDelegateClassLoader() {
ClassLoader classLoader = new TestClassLoader(this::useTestProtocolResolversFactories);
Expand Down

0 comments on commit 02498ec

Please sign in to comment.