Javadoc refinements, exception fine-tuning, general polishing
Issue: SPR-13034
This commit is contained in:
parent
2577ac300b
commit
d183bbb667
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
|
@ -19,9 +19,9 @@ package org.springframework.web.servlet.view.groovy;
|
|||
import groovy.text.markup.MarkupTemplateEngine;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by objects that configure and manage a
|
||||
* Groovy MarkupTemplateEngine for automatic lookup in a web environment.
|
||||
* Detected and used by GroovyMarkupView.
|
||||
* Interface to be implemented by objects that configure and manage a Groovy
|
||||
* {@link MarkupTemplateEngine} for automatic lookup in a web environment.
|
||||
* Detected and used by {@link GroovyMarkupView}.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @since 4.1
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
|
@ -46,7 +46,6 @@ import org.springframework.util.StringUtils;
|
|||
*
|
||||
* @Bean
|
||||
* public GroovyMarkupConfig groovyMarkupConfigurer() {
|
||||
*
|
||||
* GroovyMarkupConfigurer configurer = new GroovyMarkupConfigurer();
|
||||
* configurer.setResourceLoaderPath("classpath:/WEB-INF/groovymarkup/");
|
||||
* return configurer;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
|
@ -35,8 +35,7 @@ import org.springframework.web.servlet.view.AbstractTemplateView;
|
|||
import org.springframework.web.util.NestedServletException;
|
||||
|
||||
/**
|
||||
* An {@link org.springframework.web.servlet.view.AbstractTemplateView AbstractTemplateView}
|
||||
* based on Groovy XML/XHTML markup templates.
|
||||
* An {@link AbstractTemplateView} subclass based on Groovy XML/XHTML markup templates.
|
||||
*
|
||||
* <p>Spring's Groovy Markup Template support requires Groovy 2.3.1 and higher.
|
||||
*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
|
@ -21,10 +21,9 @@ import java.util.Locale;
|
|||
import org.springframework.web.servlet.view.AbstractTemplateViewResolver;
|
||||
|
||||
/**
|
||||
* Convenience subclass of
|
||||
* {@link org.springframework.web.servlet.view.AbstractTemplateViewResolver}
|
||||
* that supports {@link GroovyMarkupView} (i.e. Groovy XML/XHTML markup templates)
|
||||
* and custom subclasses of it.
|
||||
* Convenience subclass of @link AbstractTemplateViewResolver} that supports
|
||||
* {@link GroovyMarkupView} (i.e. Groovy XML/XHTML markup templates) and
|
||||
* custom subclasses of it.
|
||||
*
|
||||
* <p>The view class for all views created by this resolver can be specified
|
||||
* via the {@link #setViewClass(Class)} property.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* Support classes for the integration of
|
||||
* <a href="http://beta.groovy-lang.org/docs/groovy-2.3.0/html/documentation/markup-template-engine.html">
|
||||
* <a href="http://docs.groovy-lang.org/docs/next/html/documentation/template-engines.html#_the_markuptemplateengine">
|
||||
* Groovy Templates</a> as Spring web view technology.
|
||||
* Contains a View implementation for Groovy templates.
|
||||
*/
|
||||
|
|
|
@ -21,7 +21,7 @@ import javax.script.ScriptEngine;
|
|||
|
||||
/**
|
||||
* Interface to be implemented by objects that configure and manage a
|
||||
* {@link ScriptEngine} for automatic lookup in a web environment.
|
||||
* JSR-223 {@link ScriptEngine} for automatic lookup in a web environment.
|
||||
* Detected and used by {@link ScriptTemplateView}.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
|
@ -29,20 +29,45 @@ import javax.script.ScriptEngine;
|
|||
*/
|
||||
public interface ScriptTemplateConfig {
|
||||
|
||||
/**
|
||||
* Return the {@link ScriptEngine} to use by the views.
|
||||
*/
|
||||
ScriptEngine getEngine();
|
||||
|
||||
/**
|
||||
* Return the engine name that will be used to instantiate the {@link ScriptEngine}.
|
||||
*/
|
||||
String getEngineName();
|
||||
|
||||
/**
|
||||
* Return whether to use a shared engine for all threads or whether to create
|
||||
* thread-local engine instances for each thread.
|
||||
*/
|
||||
Boolean isSharedEngine();
|
||||
|
||||
/**
|
||||
* Return the scripts to be loaded by the script engine (library or user provided).
|
||||
*/
|
||||
String[] getScripts();
|
||||
|
||||
/**
|
||||
* Return the object where the render function belongs (optional).
|
||||
*/
|
||||
String getRenderObject();
|
||||
|
||||
/**
|
||||
* Return the render function name (mandatory).
|
||||
*/
|
||||
String getRenderFunction();
|
||||
|
||||
/**
|
||||
* Return the charset used to read script and template files.
|
||||
*/
|
||||
Charset getCharset();
|
||||
|
||||
/**
|
||||
* Return the resource loader path(s) via a Spring resource location.
|
||||
*/
|
||||
String getResourceLoaderPath();
|
||||
|
||||
Boolean isShareEngine();
|
||||
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
package org.springframework.web.servlet.view.script;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
|
||||
/**
|
||||
|
@ -40,9 +39,9 @@ import javax.script.ScriptEngine;
|
|||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>It is possible to use non thread-safe script engines and templating libraries, like
|
||||
* Handlebars or React running on Nashorn, by setting the
|
||||
* {@link #setSharedEngine(Boolean) sharedEngine} property to {@code false}.
|
||||
* <p><b>NOTE:</b> It is possible to use non thread-safe script engines and
|
||||
* templating libraries, like Handlebars or React running on Nashorn, by setting
|
||||
* the {@link #setSharedEngine sharedEngine} property to {@code false}.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @since 4.2
|
||||
|
@ -54,6 +53,8 @@ public class ScriptTemplateConfigurer implements ScriptTemplateConfig {
|
|||
|
||||
private String engineName;
|
||||
|
||||
private Boolean sharedEngine;
|
||||
|
||||
private String[] scripts;
|
||||
|
||||
private String renderObject;
|
||||
|
@ -64,17 +65,14 @@ public class ScriptTemplateConfigurer implements ScriptTemplateConfig {
|
|||
|
||||
private String resourceLoaderPath;
|
||||
|
||||
private Boolean sharedEngine;
|
||||
|
||||
/**
|
||||
* Set the {@link ScriptEngine} to use by the view.
|
||||
* The script engine must implement {@code Invocable}.
|
||||
* You must define {@code engine} or {@code engineName}, not both.
|
||||
*
|
||||
* <p>When the {@code sharedEngine} flag is set to {@code false}, you should not specify
|
||||
* the script engine with this setter, but with the {@link #setEngineName(String)}
|
||||
* one (since it implies multiple lazy instanciations of the script engine).
|
||||
*
|
||||
* one (since it implies multiple lazy instantiations of the script engine).
|
||||
* @see #setEngineName(String)
|
||||
*/
|
||||
public void setEngine(ScriptEngine engine) {
|
||||
|
@ -101,17 +99,35 @@ public class ScriptTemplateConfigurer implements ScriptTemplateConfig {
|
|||
return this.engineName;
|
||||
}
|
||||
|
||||
/**
|
||||
* When set to {@code false}, use thread-local {@link ScriptEngine} instances instead
|
||||
* of one single shared instance. This flag should be set to {@code false} for those
|
||||
* using non thread-safe script engines and templating libraries, like Handlebars or
|
||||
* React running on Nashorn for example.
|
||||
* <p>When this flag is set to {@code false}, the script engine must be specified using
|
||||
* {@link #setEngineName(String)}. Using {@link #setEngine(ScriptEngine)} is not
|
||||
* possible because multiple instances of the script engine need to be created lazily
|
||||
* (one per thread).
|
||||
* @see <a href="http://docs.oracle.com/javase/8/docs/api/javax/script/ScriptEngineFactory.html#getParameter-java.lang.String-">THREADING ScriptEngine parameter<a/>
|
||||
*/
|
||||
public void setSharedEngine(Boolean sharedEngine) {
|
||||
this.sharedEngine = sharedEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean isSharedEngine() {
|
||||
return this.sharedEngine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the scripts to be loaded by the script engine (library or user provided).
|
||||
* Since {@code resourceLoaderPath} default value is "classpath:", you can load easily
|
||||
* any script available on the classpath.
|
||||
*
|
||||
* For example, in order to use a Javascript library available as a WebJars dependency
|
||||
* <p>For example, in order to use a JavaScript library available as a WebJars dependency
|
||||
* and a custom "render.js" file, you should call
|
||||
* {@code configurer.setScripts("/META-INF/resources/webjars/library/version/library.js",
|
||||
* "com/myproject/script/render.js");}.
|
||||
*
|
||||
* @see #setResourceLoaderPath(String)
|
||||
* @see #setResourceLoaderPath
|
||||
* @see <a href="http://www.webjars.org">WebJars</a>
|
||||
*/
|
||||
public void setScripts(String... scriptNames) {
|
||||
|
@ -124,7 +140,7 @@ public class ScriptTemplateConfigurer implements ScriptTemplateConfig {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the object where belongs the render function (optional).
|
||||
* Set the object where the render function belongs (optional).
|
||||
* For example, in order to call {@code Mustache.render()}, {@code renderObject}
|
||||
* should be set to {@code "Mustache"} and {@code renderFunction} to {@code "render"}.
|
||||
*/
|
||||
|
@ -138,11 +154,11 @@ public class ScriptTemplateConfigurer implements ScriptTemplateConfig {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the render function name (mandatory). This function will be called with the
|
||||
* following parameters:
|
||||
* Set the render function name (mandatory).
|
||||
* This function will be called with the following parameters:
|
||||
* <ol>
|
||||
* <li>{@code template}: the view template content (String)</li>
|
||||
* <li>{@code model}: the view model (Map)</li>
|
||||
* <li>{@code template}: the view template content (String)</li>
|
||||
* <li>{@code model}: the view model (Map)</li>
|
||||
* </ol>
|
||||
*/
|
||||
public void setRenderFunction(String renderFunction) {
|
||||
|
@ -173,7 +189,7 @@ public class ScriptTemplateConfigurer implements ScriptTemplateConfig {
|
|||
* Standard URLs like "file:" and "classpath:" and pseudo URLs are supported
|
||||
* as understood by Spring's {@link org.springframework.core.io.ResourceLoader}.
|
||||
* Relative paths are allowed when running in an ApplicationContext.
|
||||
* Default is "classpath:".
|
||||
* <p>Default is "classpath:".
|
||||
*/
|
||||
public void setResourceLoaderPath(String resourceLoaderPath) {
|
||||
this.resourceLoaderPath = resourceLoaderPath;
|
||||
|
@ -184,25 +200,4 @@ public class ScriptTemplateConfigurer implements ScriptTemplateConfig {
|
|||
return this.resourceLoaderPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* When set to {@code false}, use thread-local {@link ScriptEngine} instances instead
|
||||
* of one single shared instance. This flag should be set to {@code false} for those
|
||||
* using non thread-safe script engines and templating libraries, like Handlebars or
|
||||
* React running on Nashorn for example.
|
||||
*
|
||||
* <p>When this flag is set to {@code false}, the script engine must be specified using
|
||||
* {@link #setEngineName(String)}. Using {@link #setEngine(ScriptEngine)} is not
|
||||
* possible because multiple instances of the script engine need to be created lazily
|
||||
* (one per thread).
|
||||
* @see <a href="http://docs.oracle.com/javase/8/docs/api/javax/script/ScriptEngineFactory.html#getParameter-java.lang.String-">THREADING ScriptEngine parameter<a/>
|
||||
*/
|
||||
public void setSharedEngine(Boolean sharedEngine) {
|
||||
this.sharedEngine = sharedEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean isShareEngine() {
|
||||
return this.sharedEngine;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ import java.util.Map;
|
|||
import javax.script.Invocable;
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
@ -46,8 +45,8 @@ import org.springframework.util.StringUtils;
|
|||
import org.springframework.web.servlet.view.AbstractUrlBasedView;
|
||||
|
||||
/**
|
||||
* An {@link org.springframework.web.servlet.view.AbstractUrlBasedView AbstractUrlBasedView}
|
||||
* designed to run any template library based on a JSR-223 script engine.
|
||||
* An {@link AbstractUrlBasedView} subclass designed to run any template library
|
||||
* based on a JSR-223 script engine.
|
||||
*
|
||||
* <p>If not set, each property is auto-detected by looking up up a single
|
||||
* {@link ScriptTemplateConfig} bean in the web application context and using
|
||||
|
@ -69,13 +68,14 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
|||
private static final String DEFAULT_RESOURCE_LOADER_PATH = "classpath:";
|
||||
|
||||
|
||||
private final ThreadLocal<ScriptEngine> engineHolder = new NamedThreadLocal<ScriptEngine>("ScriptTemplateView engine");
|
||||
|
||||
private ScriptEngine engine;
|
||||
|
||||
private final ThreadLocal<ScriptEngine> engineHolder =
|
||||
new NamedThreadLocal<ScriptEngine>("ScriptTemplateView engine");
|
||||
|
||||
private String engineName;
|
||||
|
||||
private Boolean sharedEngine;
|
||||
|
||||
private String[] scripts;
|
||||
|
||||
private String renderObject;
|
||||
|
@ -88,8 +88,6 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
|||
|
||||
private String resourceLoaderPath;
|
||||
|
||||
private Boolean sharedEngine;
|
||||
|
||||
|
||||
/**
|
||||
* See {@link ScriptTemplateConfigurer#setEngine(ScriptEngine)} documentation.
|
||||
|
@ -99,48 +97,6 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
|||
this.engine = engine;
|
||||
}
|
||||
|
||||
protected ScriptEngine getEngine() {
|
||||
if (Boolean.FALSE.equals(this.sharedEngine)) {
|
||||
ScriptEngine engine = this.engineHolder.get();
|
||||
if (engine == null) {
|
||||
engine = createEngineFromName();
|
||||
this.engineHolder.set(engine);
|
||||
}
|
||||
return engine;
|
||||
}
|
||||
else if (this.engine == null) {
|
||||
setEngine(createEngineFromName());
|
||||
}
|
||||
return this.engine;
|
||||
}
|
||||
|
||||
protected ScriptEngine createEngineFromName() {
|
||||
Assert.notNull(this.engineName);
|
||||
ScriptEngine engine = new ScriptEngineManager().getEngineByName(this.engineName);
|
||||
Assert.state(engine != null, "No engine \"" + this.engineName + "\" found.");
|
||||
loadScripts(engine);
|
||||
return engine;
|
||||
}
|
||||
|
||||
protected void loadScripts(ScriptEngine engine) {
|
||||
Assert.notNull(engine);
|
||||
if (this.scripts != null) {
|
||||
try {
|
||||
for (String script : this.scripts) {
|
||||
Resource resource = this.resourceLoader.getResource(script);
|
||||
Assert.state(resource.exists(), "Resource " + script + " not found.");
|
||||
engine.eval(new InputStreamReader(resource.getInputStream()));
|
||||
}
|
||||
}
|
||||
catch (ScriptException e) {
|
||||
throw new IllegalStateException("could not load script", e);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalStateException("could not load script", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link ScriptTemplateConfigurer#setEngineName(String)} documentation.
|
||||
*/
|
||||
|
@ -148,6 +104,13 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
|||
this.engineName = engineName;
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link ScriptTemplateConfigurer#setSharedEngine(Boolean)} documentation.
|
||||
*/
|
||||
public void setSharedEngine(Boolean sharedEngine) {
|
||||
this.sharedEngine = sharedEngine;
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link ScriptTemplateConfigurer#setScripts(String...)} documentation.
|
||||
*/
|
||||
|
@ -183,12 +146,6 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
|||
this.resourceLoaderPath = resourceLoaderPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link ScriptTemplateConfigurer#setSharedEngine(Boolean)} documentation.
|
||||
*/
|
||||
public void setSharedEngine(Boolean sharedEngine) {
|
||||
this.sharedEngine = sharedEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initApplicationContext(ApplicationContext context) {
|
||||
|
@ -211,36 +168,78 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
|||
this.renderFunction = viewConfig.getRenderFunction();
|
||||
}
|
||||
if (this.charset == null) {
|
||||
this.charset = viewConfig.getCharset() == null ? DEFAULT_CHARSET : viewConfig.getCharset();
|
||||
this.charset = (viewConfig.getCharset() != null ? viewConfig.getCharset() : DEFAULT_CHARSET);
|
||||
}
|
||||
if (this.resourceLoaderPath == null) {
|
||||
this.resourceLoaderPath = viewConfig.getResourceLoaderPath() == null ?
|
||||
DEFAULT_RESOURCE_LOADER_PATH : viewConfig.getResourceLoaderPath();
|
||||
this.resourceLoaderPath = (viewConfig.getResourceLoaderPath() != null ?
|
||||
viewConfig.getResourceLoaderPath() : DEFAULT_RESOURCE_LOADER_PATH);
|
||||
}
|
||||
if (this.resourceLoader == null) {
|
||||
this.resourceLoader = new DefaultResourceLoader(createClassLoader());
|
||||
}
|
||||
if (this.sharedEngine == null && viewConfig.isShareEngine() != null) {
|
||||
this.sharedEngine = viewConfig.isShareEngine();
|
||||
if (this.sharedEngine == null && viewConfig.isSharedEngine() != null) {
|
||||
this.sharedEngine = viewConfig.isSharedEngine();
|
||||
}
|
||||
|
||||
Assert.state(!(this.engine != null && this.engineName != null),
|
||||
"You should define engine or engineName properties, not both.");
|
||||
Assert.state(!(this.engine == null && this.engineName == null),
|
||||
"No script engine found, please specify valid engine or engineName properties.");
|
||||
Assert.isTrue(!(this.engine != null && this.engineName != null),
|
||||
"You should define either 'engine' or 'engineName', not both.");
|
||||
Assert.isTrue(!(this.engine == null && this.engineName == null),
|
||||
"No script engine found, please specify either 'engine' or 'engineName'.");
|
||||
|
||||
if (Boolean.FALSE.equals(this.sharedEngine)) {
|
||||
Assert.state(this.engineName != null,
|
||||
"When sharedEngine property is set to false, you should specify the " +
|
||||
"script engine using the engineName property, not the engine one.");
|
||||
Assert.isTrue(this.engineName != null,
|
||||
"When 'sharedEngine' is set to false, you should specify the " +
|
||||
"script engine using the 'engineName' property, not the 'engine' one.");
|
||||
}
|
||||
Assert.state(this.renderFunction != null, "renderFunction property must be defined.");
|
||||
|
||||
if (this.engine != null) {
|
||||
else if (this.engine != null) {
|
||||
loadScripts(this.engine);
|
||||
}
|
||||
else {
|
||||
setEngine(createEngineFromName());
|
||||
}
|
||||
|
||||
Assert.isTrue(this.renderFunction != null, "The 'renderFunction' property must be defined.");
|
||||
}
|
||||
|
||||
protected ScriptEngine getEngine() {
|
||||
if (Boolean.FALSE.equals(this.sharedEngine)) {
|
||||
ScriptEngine engine = this.engineHolder.get();
|
||||
if (engine == null) {
|
||||
engine = createEngineFromName();
|
||||
this.engineHolder.set(engine);
|
||||
}
|
||||
return engine;
|
||||
}
|
||||
else {
|
||||
// Simply return the configured ScriptEngine...
|
||||
return this.engine;
|
||||
}
|
||||
}
|
||||
|
||||
protected ScriptEngine createEngineFromName() {
|
||||
ScriptEngine engine = new ScriptEngineManager().getEngineByName(this.engineName);
|
||||
if (engine == null) {
|
||||
throw new IllegalStateException("No engine with name '" + this.engineName + "' found");
|
||||
}
|
||||
loadScripts(engine);
|
||||
return engine;
|
||||
}
|
||||
|
||||
protected void loadScripts(ScriptEngine engine) {
|
||||
if (this.scripts != null) {
|
||||
try {
|
||||
for (String script : this.scripts) {
|
||||
Resource resource = this.resourceLoader.getResource(script);
|
||||
if (!resource.exists()) {
|
||||
throw new IllegalStateException("Resource " + script + " not found");
|
||||
}
|
||||
engine.eval(new InputStreamReader(resource.getInputStream()));
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("Failed to load script", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected ClassLoader createClassLoader() {
|
||||
|
@ -257,8 +256,9 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
|||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Cannot create class loader: " + e.getMessage());
|
||||
}
|
||||
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);
|
||||
|
@ -275,30 +275,33 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
Assert.notNull("Render function must not be null", this.renderFunction);
|
||||
protected void renderMergedOutputModel(
|
||||
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
|
||||
try {
|
||||
ScriptEngine engine = getEngine();
|
||||
Invocable invocable = (Invocable) engine;
|
||||
String template = getTemplate(getUrl());
|
||||
Object html;
|
||||
if (this.renderObject != null) {
|
||||
Object thiz = engine.eval(this.renderObject);
|
||||
html = ((Invocable)getEngine()).invokeMethod(thiz, this.renderFunction, template, model);
|
||||
html = invocable.invokeMethod(thiz, this.renderFunction, template, model);
|
||||
}
|
||||
else {
|
||||
html = ((Invocable)getEngine()).invokeFunction(this.renderFunction, template, model);
|
||||
html = invocable.invokeFunction(this.renderFunction, template, model);
|
||||
}
|
||||
response.getWriter().write(String.valueOf(html));
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException("failed to render template", e);
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("Failed to render script template", ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected String getTemplate(String path) throws IOException {
|
||||
Resource resource = this.resourceLoader.getResource(path);
|
||||
Assert.state(resource.exists(), "Resource " + path + " not found.");
|
||||
return StreamUtils.copyToString(resource.getInputStream(), this.charset);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,9 +19,8 @@ package org.springframework.web.servlet.view.script;
|
|||
import org.springframework.web.servlet.view.UrlBasedViewResolver;
|
||||
|
||||
/**
|
||||
* Convenience subclass of
|
||||
* {@link org.springframework.web.servlet.view.UrlBasedViewResolver}
|
||||
* that supports {@link ScriptTemplateView} and custom subclasses of it.
|
||||
* Convenience subclass of {@link UrlBasedViewResolver} that supports
|
||||
* {@link ScriptTemplateView} and custom subclasses of it.
|
||||
*
|
||||
* <p>The view class for all views created by this resolver can be specified
|
||||
* via the {@link #setViewClass(Class)} property.
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
/**
|
||||
* Support classes for views based on the JSR-223 script engine abstraction
|
||||
* (as included in Java 6+), e.g. using JavaScript via Nashorn on JDK 8.
|
||||
* Contains a View implementation for scripted templates.
|
||||
*/
|
||||
package org.springframework.web.servlet.view.script;
|
|
@ -31,14 +31,15 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.MapperFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
||||
import org.hamcrest.Matchers;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -56,6 +57,7 @@ import org.springframework.format.annotation.DateTimeFormat;
|
|||
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
import org.springframework.format.annotation.NumberFormat;
|
||||
import org.springframework.format.support.FormattingConversionServiceFactoryBean;
|
||||
import org.springframework.http.CacheControl;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter;
|
||||
|
@ -75,7 +77,6 @@ import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
|||
import org.springframework.web.accept.ContentNegotiationManager;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.http.CacheControl;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
|
@ -141,11 +142,6 @@ import org.springframework.web.servlet.view.velocity.VelocityConfigurer;
|
|||
import org.springframework.web.servlet.view.velocity.VelocityViewResolver;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.MapperFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
|
@ -807,7 +803,7 @@ public class MvcNamespaceTests {
|
|||
assertEquals("render", scriptTemplateConfigurer.getRenderFunction());
|
||||
assertEquals(StandardCharsets.ISO_8859_1, scriptTemplateConfigurer.getCharset());
|
||||
assertEquals("classpath:", scriptTemplateConfigurer.getResourceLoaderPath());
|
||||
assertFalse(scriptTemplateConfigurer.isShareEngine());
|
||||
assertFalse(scriptTemplateConfigurer.isSharedEngine());
|
||||
String[] scripts = { "org/springframework/web/servlet/view/script/nashorn/render.js" };
|
||||
accessor = new DirectFieldAccessor(scriptTemplateConfigurer);
|
||||
assertArrayEquals(scripts, (String[]) accessor.getPropertyValue("scripts"));
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
|
@ -13,6 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.servlet.view.script;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
|
|
@ -28,19 +28,18 @@ import javax.script.Invocable;
|
|||
import javax.script.ScriptEngine;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.BDDMockito.*;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ScriptTemplateView}.
|
||||
*
|
||||
|
@ -149,11 +148,12 @@ public class ScriptTemplateViewTests {
|
|||
public void nonInvocableScriptEngine() throws Exception {
|
||||
try {
|
||||
this.view.setEngine(mock(ScriptEngine.class));
|
||||
} catch(IllegalArgumentException ex) {
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
assertThat(ex.getMessage(), containsString("instance"));
|
||||
return;
|
||||
}
|
||||
fail();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -161,11 +161,11 @@ public class ScriptTemplateViewTests {
|
|||
this.view.setEngine(mock(InvocableScriptEngine.class));
|
||||
try {
|
||||
this.view.setApplicationContext(this.applicationContext);
|
||||
} catch(IllegalStateException ex) {
|
||||
assertThat(ex.getMessage(), containsString("renderFunction"));
|
||||
return;
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
assertThat(ex.getMessage(), containsString("renderFunction"));
|
||||
}
|
||||
fail();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -175,11 +175,11 @@ public class ScriptTemplateViewTests {
|
|||
this.view.setRenderFunction("render");
|
||||
try {
|
||||
this.view.setApplicationContext(this.applicationContext);
|
||||
} catch(IllegalStateException ex) {
|
||||
assertThat(ex.getMessage(), containsString("engine or engineName"));
|
||||
return;
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
assertThat(ex.getMessage(), containsString("'engine' or 'engineName'"));
|
||||
}
|
||||
fail();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -189,7 +189,9 @@ public class ScriptTemplateViewTests {
|
|||
this.view.setSharedEngine(false);
|
||||
try {
|
||||
this.view.setApplicationContext(this.applicationContext);
|
||||
} catch(IllegalStateException ex) {
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
assertThat(ex.getMessage(), containsString("sharedEngine"));
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue