Revisit ScriptTemplateView resource loading
Resources are now retrieved using the application context in order to support natively non-classpath locations like /WEB-INF/... As a consequence of this refactoring, ScriptTemplateView#createClassLoader() protected method as been removed, since it did not make sense anymore with this new resource loading implementation. Issue: SPR-14210
This commit is contained in:
parent
9412f7a094
commit
15138ed96f
|
@ -18,8 +18,6 @@ package org.springframework.web.servlet.view.script;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -40,7 +38,6 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
|||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.scripting.support.StandardScriptEvalException;
|
||||
|
@ -96,7 +93,7 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
|||
|
||||
private Charset charset;
|
||||
|
||||
private String resourceLoaderPath;
|
||||
private String[] resourceLoaderPaths;
|
||||
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
|
@ -184,7 +181,16 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
|||
* See {@link ScriptTemplateConfigurer#setResourceLoaderPath(String)} documentation.
|
||||
*/
|
||||
public void setResourceLoaderPath(String resourceLoaderPath) {
|
||||
this.resourceLoaderPath = resourceLoaderPath;
|
||||
String[] paths = StringUtils.commaDelimitedListToStringArray(resourceLoaderPath);
|
||||
this.resourceLoaderPaths = new String[paths.length + 1];
|
||||
this.resourceLoaderPaths[0] = "";
|
||||
for (int i = 0; i < paths.length; i++) {
|
||||
String path = paths[i];
|
||||
if (!path.endsWith("/") && !path.endsWith(":")) {
|
||||
path = path + "/";
|
||||
}
|
||||
this.resourceLoaderPaths[i + 1] = path;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -214,12 +220,12 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
|||
if (this.charset == null) {
|
||||
this.charset = (viewConfig.getCharset() != null ? viewConfig.getCharset() : DEFAULT_CHARSET);
|
||||
}
|
||||
if (this.resourceLoaderPath == null) {
|
||||
this.resourceLoaderPath = (viewConfig.getResourceLoaderPath() != null ?
|
||||
viewConfig.getResourceLoaderPath() : DEFAULT_RESOURCE_LOADER_PATH);
|
||||
if (this.resourceLoaderPaths == null) {
|
||||
String resourceLoaderPath = viewConfig.getResourceLoaderPath();
|
||||
setResourceLoaderPath(resourceLoaderPath == null ? DEFAULT_RESOURCE_LOADER_PATH : resourceLoaderPath);
|
||||
}
|
||||
if (this.resourceLoader == null) {
|
||||
this.resourceLoader = new DefaultResourceLoader(createClassLoader());
|
||||
this.resourceLoader = getApplicationContext();
|
||||
}
|
||||
if (this.sharedEngine == null && viewConfig.isSharedEngine() != null) {
|
||||
this.sharedEngine = viewConfig.isSharedEngine();
|
||||
|
@ -282,10 +288,7 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
|||
if (!ObjectUtils.isEmpty(this.scripts)) {
|
||||
try {
|
||||
for (String script : this.scripts) {
|
||||
Resource resource = this.resourceLoader.getResource(script);
|
||||
if (!resource.exists()) {
|
||||
throw new IllegalStateException("Script resource [" + script + "] not found");
|
||||
}
|
||||
Resource resource = getResource(script);
|
||||
engine.eval(new InputStreamReader(resource.getInputStream()));
|
||||
}
|
||||
}
|
||||
|
@ -295,26 +298,14 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
|||
}
|
||||
}
|
||||
|
||||
protected ClassLoader createClassLoader() {
|
||||
String[] paths = StringUtils.commaDelimitedListToStringArray(this.resourceLoaderPath);
|
||||
List<URL> urls = new ArrayList<URL>();
|
||||
try {
|
||||
for (String path : paths) {
|
||||
Resource[] resources = getApplicationContext().getResources(path);
|
||||
if (resources.length > 0) {
|
||||
for (Resource resource : resources) {
|
||||
if (resource.exists()) {
|
||||
urls.add(resource.getURL());
|
||||
}
|
||||
}
|
||||
}
|
||||
protected Resource getResource(String location) {
|
||||
for (String path : this.resourceLoaderPaths) {
|
||||
Resource resource = this.resourceLoader.getResource(path + location);
|
||||
if (resource.exists()) {
|
||||
return resource;
|
||||
}
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException("Cannot create class loader: " + ex.getMessage());
|
||||
}
|
||||
ClassLoader classLoader = getApplicationContext().getClassLoader();
|
||||
return (urls.size() > 0 ? new URLClassLoader(urls.toArray(new URL[urls.size()]), classLoader) : classLoader);
|
||||
throw new IllegalStateException("Resource [" + location + "] not found");
|
||||
}
|
||||
|
||||
protected ScriptTemplateConfig autodetectViewConfig() throws BeansException {
|
||||
|
@ -329,7 +320,6 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void prepareResponse(HttpServletRequest request, HttpServletResponse response) {
|
||||
super.prepareResponse(request, response);
|
||||
|
@ -365,7 +355,7 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
|||
}
|
||||
|
||||
protected String getTemplate(String path) throws IOException {
|
||||
Resource resource = this.resourceLoader.getResource(path);
|
||||
Resource resource = getResource(path);
|
||||
InputStreamReader reader = new InputStreamReader(resource.getInputStream(), this.charset);
|
||||
return FileCopyUtils.copyToString(reader);
|
||||
}
|
||||
|
|
|
@ -16,10 +16,8 @@
|
|||
|
||||
package org.springframework.web.servlet.view.script;
|
||||
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -29,8 +27,6 @@ import java.util.concurrent.Future;
|
|||
import javax.script.Invocable;
|
||||
import javax.script.ScriptEngine;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -62,8 +58,6 @@ public class ScriptTemplateViewTests {
|
|||
|
||||
private StaticWebApplicationContext wac;
|
||||
|
||||
private static final String RESOURCE_LOADER_PATH = "classpath:org/springframework/web/servlet/view/script/";
|
||||
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
|
@ -71,7 +65,6 @@ public class ScriptTemplateViewTests {
|
|||
this.wac = new StaticWebApplicationContext();
|
||||
this.wac.getBeanFactory().registerSingleton("scriptTemplateConfigurer", this.configurer);
|
||||
this.view = new ScriptTemplateView();
|
||||
this.view.setUrl(RESOURCE_LOADER_PATH + "empty.txt");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -211,26 +204,35 @@ public class ScriptTemplateViewTests {
|
|||
fail();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("resource")
|
||||
public void parentLoader() {
|
||||
this.view.setEngine(mock(InvocableScriptEngine.class));
|
||||
@Test // SPR-14210
|
||||
public void resourceLoaderPath() throws Exception {
|
||||
MockServletContext servletContext = new MockServletContext();
|
||||
this.wac.setServletContext(servletContext);
|
||||
this.wac.refresh();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.wac);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
InvocableScriptEngine engine = mock(InvocableScriptEngine.class);
|
||||
when(engine.invokeFunction(any(), any(), any(), any())).thenReturn("foo");
|
||||
this.view.setEngine(engine);
|
||||
this.view.setRenderFunction("render");
|
||||
this.view.setResourceLoaderPath(RESOURCE_LOADER_PATH);
|
||||
this.view.setApplicationContext(this.wac);
|
||||
ClassLoader classLoader = this.view.createClassLoader();
|
||||
assertNotNull(classLoader);
|
||||
URLClassLoader urlClassLoader = (URLClassLoader) classLoader;
|
||||
assertThat(Arrays.asList(urlClassLoader.getURLs()), Matchers.hasSize(1));
|
||||
assertThat(Arrays.asList(urlClassLoader.getURLs()).get(0).toString(),
|
||||
Matchers.endsWith("org/springframework/web/servlet/view/script/"));
|
||||
this.view.setResourceLoaderPath(RESOURCE_LOADER_PATH + ",classpath:org/springframework/web/servlet/view/");
|
||||
classLoader = this.view.createClassLoader();
|
||||
assertNotNull(classLoader);
|
||||
urlClassLoader = (URLClassLoader) classLoader;
|
||||
assertThat(Arrays.asList(urlClassLoader.getURLs()), Matchers.hasSize(2));
|
||||
assertThat(Arrays.asList(urlClassLoader.getURLs()).get(0).toString(), Matchers.endsWith("org/springframework/web/servlet/view/script/"));
|
||||
assertThat(Arrays.asList(urlClassLoader.getURLs()).get(1).toString(), Matchers.endsWith("org/springframework/web/servlet/view/"));
|
||||
this.view.setUrl("org/springframework/web/servlet/view/script/empty.txt");
|
||||
this.view.render(model, request, response);
|
||||
assertEquals("foo", response.getContentAsString());
|
||||
|
||||
response = new MockHttpServletResponse();
|
||||
this.view.setResourceLoaderPath("classpath:org/springframework/web/servlet/view/script/");
|
||||
this.view.setUrl("empty.txt");
|
||||
this.view.render(model, request, response);
|
||||
assertEquals("foo", response.getContentAsString());
|
||||
|
||||
response = new MockHttpServletResponse();
|
||||
this.view.setResourceLoaderPath("classpath:org/springframework/web/servlet/view/script");
|
||||
this.view.setUrl("empty.txt");
|
||||
this.view.render(model, request, response);
|
||||
assertEquals("foo", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test // SPR-13379
|
||||
|
@ -244,7 +246,8 @@ public class ScriptTemplateViewTests {
|
|||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
this.view.setEngine(mock(InvocableScriptEngine.class));
|
||||
this.view.setRenderFunction("render");
|
||||
this.view.setResourceLoaderPath(RESOURCE_LOADER_PATH);
|
||||
this.view.setResourceLoaderPath("classpath:org/springframework/web/servlet/view/script/");
|
||||
this.view.setUrl("empty.txt");
|
||||
this.view.setApplicationContext(this.wac);
|
||||
|
||||
this.view.render(model, request, response);
|
||||
|
|
Loading…
Reference in New Issue