Check template availability in ScriptTemplateView

This commit overrides the `checkResource` implementation in
`ScriptTemplateView` in order to check if the template file resource is
available and if the resolver can then proceed with rendering the
template.

Issue: SPR-14729
Cherry-picked from: 97c9b05c15
This commit is contained in:
Brian Clozel 2016-09-17 22:18:55 +02:00
parent 2bbfbb1d50
commit 66b370e103
2 changed files with 48 additions and 35 deletions

View File

@ -16,11 +16,13 @@
package org.springframework.web.servlet.view.script; package org.springframework.web.servlet.view.script;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import javax.script.Invocable; import javax.script.Invocable;
import javax.script.ScriptEngine; import javax.script.ScriptEngine;
@ -191,6 +193,19 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
} }
} }
@Override
public boolean checkResource(Locale locale) throws Exception {
try {
getTemplate(getUrl());
return true;
}
catch (IllegalStateException exc) {
if (logger.isDebugEnabled()) {
logger.debug("No ScriptTemplate view found for URL: " + getUrl());
}
return false;
}
}
@Override @Override
protected void initApplicationContext(ApplicationContext context) { protected void initApplicationContext(ApplicationContext context) {

View File

@ -20,6 +20,7 @@ import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@ -28,7 +29,9 @@ import javax.script.Invocable;
import javax.script.ScriptEngine; import javax.script.ScriptEngine;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.DirectFieldAccessor;
import org.springframework.context.ApplicationContextException; import org.springframework.context.ApplicationContextException;
@ -58,6 +61,8 @@ public class ScriptTemplateViewTests {
private StaticWebApplicationContext wac; private StaticWebApplicationContext wac;
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Before @Before
public void setup() { public void setup() {
@ -68,15 +73,24 @@ public class ScriptTemplateViewTests {
} }
@Test
public void missingTemplate() throws Exception {
MockServletContext servletContext = new MockServletContext();
this.wac.setServletContext(servletContext);
this.wac.refresh();
this.view.setResourceLoaderPath("classpath:org/springframework/web/servlet/view/script/");
this.view.setUrl("missing.txt");
this.view.setEngine(mock(InvocableScriptEngine.class));
this.configurer.setRenderFunction("render");
this.view.setApplicationContext(this.wac);
assertFalse(this.view.checkResource(Locale.ENGLISH));
}
@Test @Test
public void missingScriptTemplateConfig() throws Exception { public void missingScriptTemplateConfig() throws Exception {
try { this.expectedException.expect(ApplicationContextException.class);
this.view.setApplicationContext(new StaticApplicationContext()); this.view.setApplicationContext(new StaticApplicationContext());
fail("Should have thrown ApplicationContextException"); this.expectedException.expectMessage(contains("ScriptTemplateConfig"));
}
catch (ApplicationContextException ex) {
assertTrue(ex.getMessage().contains("ScriptTemplateConfig"));
}
} }
@Test @Test
@ -152,25 +166,17 @@ public class ScriptTemplateViewTests {
@Test @Test
public void nonInvocableScriptEngine() throws Exception { public void nonInvocableScriptEngine() throws Exception {
try { this.expectedException.expect(IllegalArgumentException.class);
this.view.setEngine(mock(ScriptEngine.class)); this.view.setEngine(mock(ScriptEngine.class));
fail("Should have thrown IllegalArgumentException"); this.expectedException.expectMessage(contains("instance"));
}
catch (IllegalArgumentException ex) {
assertThat(ex.getMessage(), containsString("instance"));
}
} }
@Test @Test
public void noRenderFunctionDefined() { public void noRenderFunctionDefined() {
this.view.setEngine(mock(InvocableScriptEngine.class)); this.view.setEngine(mock(InvocableScriptEngine.class));
try { this.expectedException.expect(IllegalArgumentException.class);
this.view.setApplicationContext(this.wac); this.view.setApplicationContext(this.wac);
fail("Should have thrown IllegalArgumentException"); this.expectedException.expectMessage(contains("renderFunction"));
}
catch (IllegalArgumentException ex) {
assertThat(ex.getMessage(), containsString("renderFunction"));
}
} }
@Test @Test
@ -178,13 +184,9 @@ public class ScriptTemplateViewTests {
this.view.setEngine(mock(InvocableScriptEngine.class)); this.view.setEngine(mock(InvocableScriptEngine.class));
this.view.setEngineName("test"); this.view.setEngineName("test");
this.view.setRenderFunction("render"); this.view.setRenderFunction("render");
try { this.expectedException.expect(IllegalArgumentException.class);
this.view.setApplicationContext(this.wac); this.view.setApplicationContext(this.wac);
fail("Should have thrown IllegalArgumentException"); this.expectedException.expectMessage(contains("'engine' or 'engineName'"));
}
catch (IllegalArgumentException ex) {
assertThat(ex.getMessage(), containsString("'engine' or 'engineName'"));
}
} }
@Test @Test
@ -192,13 +194,9 @@ public class ScriptTemplateViewTests {
this.view.setEngine(mock(InvocableScriptEngine.class)); this.view.setEngine(mock(InvocableScriptEngine.class));
this.view.setRenderFunction("render"); this.view.setRenderFunction("render");
this.view.setSharedEngine(false); this.view.setSharedEngine(false);
try { this.expectedException.expect(IllegalArgumentException.class);
this.view.setApplicationContext(this.wac); this.view.setApplicationContext(this.wac);
fail("Should have thrown IllegalArgumentException"); this.expectedException.expectMessage(contains("sharedEngine"));
}
catch (IllegalArgumentException ex) {
assertThat(ex.getMessage(), containsString("sharedEngine"));
}
} }
@Test // SPR-14210 @Test // SPR-14210