-
Notifications
You must be signed in to change notification settings - Fork 38k
/
ScriptTemplateConfigurer.java
225 lines (193 loc) · 6.85 KB
/
ScriptTemplateConfigurer.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/*
* 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.servlet.view.script;
import java.nio.charset.Charset;
import javax.script.ScriptEngine;
/**
* An implementation of Spring MVC's {@link ScriptTemplateConfig} for creating
* a {@code ScriptEngine} for use in a web application.
*
* <pre class="code">
*
* // Add the following to an @Configuration class
* @Bean
* public ScriptTemplateConfigurer mustacheConfigurer() {
* ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer();
* configurer.setEngineName("nashorn");
* configurer.setScripts("mustache.js");
* configurer.setRenderObject("Mustache");
* configurer.setRenderFunction("render");
* return configurer;
* }
* </pre>
*
* <p><b>NOTE:</b> It is possible to use non thread-safe script engines with
* templating libraries not designed for concurrency, like Handlebars or React running on
* Nashorn, by setting the {@link #setSharedEngine sharedEngine} property to {@code false}.
*
* @author Sebastien Deleuze
* @since 4.2
* @see ScriptTemplateView
*/
public class ScriptTemplateConfigurer implements ScriptTemplateConfig {
private ScriptEngine engine;
private String engineName;
private Boolean sharedEngine;
private String[] scripts;
private String renderObject;
private String renderFunction;
private String contentType;
private Charset charset;
private String resourceLoaderPath;
/**
* 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 instantiations of the script engine).
* @see #setEngineName(String)
*/
public void setEngine(ScriptEngine engine) {
this.engine = engine;
}
@Override
public ScriptEngine getEngine() {
return this.engine;
}
/**
* Set the engine name that will be used to instantiate the {@link ScriptEngine}.
* The script engine must implement {@code Invocable}.
* You must define {@code engine} or {@code engineName}, not both.
* @see #setEngine(ScriptEngine)
*/
public void setEngineName(String engineName) {
this.engineName = engineName;
}
@Override
public String getEngineName() {
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 with templating libraries not designed for
* concurrency, like Handlebars or React running on Nashorn for example.
* In this case, Java 8u60 or greater is required due to
* <a href="https://bugs.openjdk.java.net/browse/JDK-8076099">this bug</a>.
* <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="https://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.
* <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
* @see <a href="https://www.webjars.org">WebJars</a>
*/
public void setScripts(String... scriptNames) {
this.scripts = scriptNames;
}
@Override
public String[] getScripts() {
return this.scripts;
}
/**
* 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"}.
*/
public void setRenderObject(String renderObject) {
this.renderObject = renderObject;
}
@Override
public String getRenderObject() {
return this.renderObject;
}
/**
* Set the render function name (mandatory).
*
* <p>This function will be called with the following parameters:
* <ol>
* <li>{@code String template}: the template content</li>
* <li>{@code Map model}: the view model</li>
* <li>{@code String url}: the template url (since 4.2.2)</li>
* </ol>
*/
public void setRenderFunction(String renderFunction) {
this.renderFunction = renderFunction;
}
@Override
public String getRenderFunction() {
return this.renderFunction;
}
/**
* Set the content type to use for the response.
* ({@code text/html} by default).
* @since 4.2.1
*/
public void setContentType(String contentType) {
this.contentType = contentType;
}
/**
* Return the content type to use for the response.
* @since 4.2.1
*/
@Override
public String getContentType() {
return this.contentType;
}
/**
* Set the charset used to read script and template files.
* ({@code UTF-8} by default).
*/
public void setCharset(Charset charset) {
this.charset = charset;
}
@Override
public Charset getCharset() {
return this.charset;
}
/**
* Set the resource loader path(s) via a Spring resource location.
* Accepts multiple locations as a comma-separated list of paths.
* 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.
* <p>Default is "classpath:".
*/
public void setResourceLoaderPath(String resourceLoaderPath) {
this.resourceLoaderPath = resourceLoaderPath;
}
@Override
public String getResourceLoaderPath() {
return this.resourceLoaderPath;
}
}