1 |
|
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
|
|
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
|
20 |
|
package org.xwiki.rendering.macro.script; |
21 |
|
|
22 |
|
import java.io.Reader; |
23 |
|
import java.io.StringWriter; |
24 |
|
import java.io.Writer; |
25 |
|
import java.util.Collections; |
26 |
|
import java.util.HashMap; |
27 |
|
import java.util.List; |
28 |
|
import java.util.Map; |
29 |
|
|
30 |
|
import javax.inject.Inject; |
31 |
|
import javax.script.Compilable; |
32 |
|
import javax.script.CompiledScript; |
33 |
|
import javax.script.ScriptContext; |
34 |
|
import javax.script.ScriptEngine; |
35 |
|
import javax.script.ScriptEngineManager; |
36 |
|
import javax.script.ScriptException; |
37 |
|
|
38 |
|
import org.apache.commons.lang3.StringUtils; |
39 |
|
import org.xwiki.component.phase.InitializationException; |
40 |
|
import org.xwiki.context.ExecutionContext; |
41 |
|
import org.xwiki.properties.ConverterManager; |
42 |
|
import org.xwiki.rendering.block.Block; |
43 |
|
import org.xwiki.rendering.block.Block.Axes; |
44 |
|
import org.xwiki.rendering.block.MetaDataBlock; |
45 |
|
import org.xwiki.rendering.block.XDOM; |
46 |
|
import org.xwiki.rendering.block.match.MetadataBlockMatcher; |
47 |
|
import org.xwiki.rendering.listener.MetaData; |
48 |
|
import org.xwiki.rendering.macro.MacroExecutionException; |
49 |
|
import org.xwiki.rendering.macro.descriptor.ContentDescriptor; |
50 |
|
import org.xwiki.rendering.transformation.MacroTransformationContext; |
51 |
|
import org.xwiki.script.ScriptContextManager; |
52 |
|
|
53 |
|
|
54 |
|
|
55 |
|
|
56 |
|
@param |
57 |
|
@version |
58 |
|
@since |
59 |
|
|
|
|
| 87.4% |
Uncovered Elements: 13 (103) |
Complexity: 29 |
Complexity Density: 0.43 |
|
60 |
|
public abstract class AbstractJSR223ScriptMacro<P extends JSR223ScriptMacroParameters> extends AbstractScriptMacro<P> |
61 |
|
implements PrivilegedScriptMacro |
62 |
|
{ |
63 |
|
|
64 |
|
|
65 |
|
@link |
66 |
|
|
67 |
|
public static final String BINDING_CONTEXT = "context"; |
68 |
|
|
69 |
|
|
70 |
|
|
71 |
|
|
72 |
|
public static final String BINDING_OUT = "out"; |
73 |
|
|
74 |
|
|
75 |
|
@link |
76 |
|
|
77 |
|
private static final String EXECUTION_CONTEXT_ENGINE_KEY = "scriptEngines"; |
78 |
|
|
79 |
|
|
80 |
|
|
81 |
|
|
82 |
|
protected ScriptEngineManager scriptEngineManager; |
83 |
|
|
84 |
|
|
85 |
|
|
86 |
|
|
87 |
|
@Inject |
88 |
|
private ScriptContextManager scriptContextManager; |
89 |
|
|
90 |
|
@Inject |
91 |
|
private ConverterManager converterManager; |
92 |
|
|
93 |
|
|
94 |
|
@param |
95 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
96 |
0 |
public AbstractJSR223ScriptMacro(String macroName)... |
97 |
|
{ |
98 |
0 |
super(macroName, null, JSR223ScriptMacroParameters.class); |
99 |
|
} |
100 |
|
|
101 |
|
|
102 |
|
@param |
103 |
|
@param |
104 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
105 |
0 |
public AbstractJSR223ScriptMacro(String macroName, String macroDescription)... |
106 |
|
{ |
107 |
0 |
super(macroName, macroDescription, JSR223ScriptMacroParameters.class); |
108 |
|
} |
109 |
|
|
110 |
|
|
111 |
|
@param |
112 |
|
@param |
113 |
|
@param |
114 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
115 |
33 |
public AbstractJSR223ScriptMacro(String macroName, String macroDescription, ContentDescriptor contentDescriptor)... |
116 |
|
{ |
117 |
33 |
super(macroName, macroDescription, contentDescriptor, JSR223ScriptMacroParameters.class); |
118 |
|
} |
119 |
|
|
120 |
|
|
121 |
|
@param |
122 |
|
@param |
123 |
|
@param |
124 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
125 |
0 |
public AbstractJSR223ScriptMacro(String macroName, String macroDescription,... |
126 |
|
Class< ? extends JSR223ScriptMacroParameters> parametersBeanClass) |
127 |
|
{ |
128 |
0 |
super(macroName, macroDescription, parametersBeanClass); |
129 |
|
} |
130 |
|
|
131 |
|
|
132 |
|
@param |
133 |
|
@param |
134 |
|
@param |
135 |
|
@param |
136 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
137 |
12 |
public AbstractJSR223ScriptMacro(String macroName, String macroDescription, ContentDescriptor contentDescriptor,... |
138 |
|
Class< ? extends JSR223ScriptMacroParameters> parametersBeanClass) |
139 |
|
{ |
140 |
12 |
super(macroName, macroDescription, contentDescriptor, parametersBeanClass); |
141 |
|
} |
142 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 0.5 |
|
143 |
41 |
@Override... |
144 |
|
public void initialize() throws InitializationException |
145 |
|
{ |
146 |
41 |
super.initialize(); |
147 |
41 |
this.scriptEngineManager = new ScriptEngineManager(); |
148 |
|
} |
149 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
150 |
13 |
@Override... |
151 |
|
public boolean supportsInlineMode() |
152 |
|
{ |
153 |
13 |
return true; |
154 |
|
} |
155 |
|
|
156 |
|
|
157 |
|
|
158 |
|
|
159 |
|
@param |
160 |
|
@param |
161 |
|
@return |
162 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
163 |
100 |
protected String getScriptEngineName(P parameters, MacroTransformationContext context)... |
164 |
|
{ |
165 |
100 |
return context.getCurrentMacroBlock().getId().toLowerCase(); |
166 |
|
} |
167 |
|
|
168 |
|
|
169 |
|
|
170 |
|
|
171 |
|
@return |
172 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
173 |
102 |
protected ScriptContext getScriptContext()... |
174 |
|
{ |
175 |
102 |
return this.scriptContextManager.getScriptContext(); |
176 |
|
} |
177 |
|
|
|
|
| 84.2% |
Uncovered Elements: 3 (19) |
Complexity: 5 |
Complexity Density: 0.38 |
|
178 |
113 |
@Override... |
179 |
|
protected List<Block> evaluateBlock(P parameters, String content, MacroTransformationContext context) |
180 |
|
throws MacroExecutionException |
181 |
|
{ |
182 |
113 |
if (StringUtils.isEmpty(content)) { |
183 |
0 |
return Collections.emptyList(); |
184 |
|
} |
185 |
|
|
186 |
113 |
String engineName = getScriptEngineName(parameters, context); |
187 |
|
|
188 |
113 |
List<Block> result; |
189 |
113 |
if (engineName != null) { |
190 |
103 |
try { |
191 |
103 |
ScriptEngine engine = getScriptEngine(engineName); |
192 |
|
|
193 |
103 |
if (engine != null) { |
194 |
102 |
result = evaluateBlock(engine, parameters, content, context); |
195 |
|
} else { |
196 |
1 |
throw new MacroExecutionException("Can't find script engine with name [" + engineName + "]"); |
197 |
|
} |
198 |
|
} catch (ScriptException e) { |
199 |
0 |
throw new MacroExecutionException("Failed to evaluate Script Macro for content [" + content + "]", e); |
200 |
|
} |
201 |
|
|
202 |
|
} else { |
203 |
|
|
204 |
10 |
result = parseScriptResult(content, parameters, context); |
205 |
|
} |
206 |
|
|
207 |
112 |
return result; |
208 |
|
} |
209 |
|
|
210 |
|
|
211 |
|
@link |
212 |
|
|
213 |
|
@param |
214 |
|
@param |
215 |
|
@param |
216 |
|
@param |
217 |
|
@return |
218 |
|
@throws |
219 |
|
@throws |
220 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (23) |
Complexity: 2 |
Complexity Density: 0.1 |
|
221 |
102 |
protected List<Block> evaluateBlock(ScriptEngine engine, P parameters, String content,... |
222 |
|
MacroTransformationContext context) throws ScriptException, MacroExecutionException |
223 |
|
{ |
224 |
102 |
List<Block> result; |
225 |
|
|
226 |
102 |
ScriptContext scriptContext = getScriptContext(); |
227 |
|
|
228 |
102 |
Writer currentWriter = scriptContext.getWriter(); |
229 |
102 |
Reader currentReader = scriptContext.getReader(); |
230 |
102 |
Object currentContextBinding = scriptContext.getAttribute(BINDING_CONTEXT, ScriptContext.ENGINE_SCOPE); |
231 |
102 |
Object currentFilename = scriptContext.getAttribute(ScriptEngine.FILENAME, ScriptContext.ENGINE_SCOPE); |
232 |
|
|
233 |
102 |
Object currentOut = scriptContext.getAttribute(BINDING_OUT, ScriptContext.ENGINE_SCOPE); |
234 |
|
|
235 |
102 |
MetaDataBlock metaDataBlock = |
236 |
|
context.getCurrentMacroBlock().getFirstBlock(new MetadataBlockMatcher(MetaData.SOURCE), |
237 |
|
Axes.ANCESTOR_OR_SELF); |
238 |
102 |
if (metaDataBlock != null) { |
239 |
68 |
scriptContext.setAttribute(ScriptEngine.FILENAME, metaDataBlock.getMetaData().getMetaData(MetaData.SOURCE), |
240 |
|
ScriptContext.ENGINE_SCOPE); |
241 |
|
} |
242 |
|
|
243 |
102 |
try { |
244 |
102 |
StringWriter stringWriter = new StringWriter(); |
245 |
|
|
246 |
|
|
247 |
102 |
scriptContext.setWriter(stringWriter); |
248 |
|
|
249 |
102 |
Object scriptResult = eval(content, engine, scriptContext); |
250 |
|
|
251 |
102 |
result = convertScriptExecution(scriptResult, stringWriter, parameters, context); |
252 |
|
} finally { |
253 |
|
|
254 |
102 |
scriptContext.setWriter(currentWriter); |
255 |
|
|
256 |
102 |
scriptContext.setReader(currentReader); |
257 |
|
|
258 |
102 |
scriptContext.setAttribute(BINDING_CONTEXT, currentContextBinding, ScriptContext.ENGINE_SCOPE); |
259 |
|
|
260 |
102 |
scriptContext.setAttribute(ScriptEngine.FILENAME, currentFilename, ScriptContext.ENGINE_SCOPE); |
261 |
|
|
262 |
102 |
scriptContext.setAttribute(BINDING_OUT, currentOut, ScriptContext.ENGINE_SCOPE); |
263 |
|
} |
264 |
|
|
265 |
102 |
return result; |
266 |
|
} |
267 |
|
|
|
|
| 90% |
Uncovered Elements: 2 (20) |
Complexity: 8 |
Complexity Density: 0.67 |
|
268 |
102 |
private List<Block> convertScriptExecution(Object scriptResult, StringWriter scriptContextWriter, P parameters,... |
269 |
|
MacroTransformationContext context) throws MacroExecutionException |
270 |
|
{ |
271 |
102 |
List<Block> result; |
272 |
|
|
273 |
102 |
if (scriptResult instanceof XDOM) { |
274 |
0 |
result = ((XDOM) scriptResult).getChildren(); |
275 |
102 |
} else if (scriptResult instanceof Block) { |
276 |
1 |
result = Collections.singletonList((Block) scriptResult); |
277 |
101 |
} else if (scriptResult instanceof List && !((List< ? >) scriptResult).isEmpty() |
278 |
|
&& ((List< ? >) scriptResult).get(0) instanceof Block) { |
279 |
1 |
result = (List<Block>) scriptResult; |
280 |
|
} else { |
281 |
|
|
282 |
|
|
283 |
100 |
String contentToParse = scriptContextWriter.toString(); |
284 |
100 |
if (StringUtils.isEmpty(contentToParse) && scriptResult != null) { |
285 |
|
|
286 |
15 |
contentToParse = this.converterManager.convert(String.class, scriptResult); |
287 |
|
} |
288 |
|
|
289 |
100 |
result = parseScriptResult(contentToParse, parameters, context); |
290 |
|
} |
291 |
|
|
292 |
102 |
return result; |
293 |
|
} |
294 |
|
|
295 |
|
|
296 |
|
@param |
297 |
|
@return |
298 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (14) |
Complexity: 3 |
Complexity Density: 0.3 |
|
299 |
103 |
private ScriptEngine getScriptEngine(String engineName)... |
300 |
|
{ |
301 |
|
|
302 |
|
|
303 |
|
|
304 |
|
|
305 |
|
|
306 |
|
|
307 |
|
|
308 |
|
|
309 |
|
|
310 |
103 |
ExecutionContext executionContext = this.execution.getContext(); |
311 |
103 |
Map<String, ScriptEngine> scriptEngines = |
312 |
|
(Map<String, ScriptEngine>) executionContext.getProperty(EXECUTION_CONTEXT_ENGINE_KEY); |
313 |
103 |
if (scriptEngines == null) { |
314 |
95 |
scriptEngines = new HashMap<String, ScriptEngine>(); |
315 |
95 |
executionContext.setProperty(EXECUTION_CONTEXT_ENGINE_KEY, scriptEngines); |
316 |
|
} |
317 |
103 |
ScriptEngine engine = scriptEngines.get(engineName); |
318 |
|
|
319 |
103 |
if (engine == null) { |
320 |
95 |
engine = this.scriptEngineManager.getEngineByName(engineName); |
321 |
95 |
scriptEngines.put(engineName, engine); |
322 |
|
} |
323 |
|
|
324 |
103 |
return engine; |
325 |
|
} |
326 |
|
|
327 |
|
|
328 |
|
|
329 |
|
|
330 |
|
@param |
331 |
|
@param |
332 |
|
@param |
333 |
|
@return |
334 |
|
@throws |
335 |
|
|
336 |
|
|
337 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
338 |
102 |
protected Object eval(String content, ScriptEngine engine, ScriptContext scriptContext) throws ScriptException... |
339 |
|
{ |
340 |
102 |
return engine.eval(content, scriptContext); |
341 |
|
} |
342 |
|
|
343 |
|
|
344 |
|
|
345 |
|
|
346 |
|
|
347 |
|
|
348 |
|
|
349 |
|
@param |
350 |
|
@param |
351 |
|
@return |
352 |
|
@throws |
353 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
354 |
0 |
protected CompiledScript getCompiledScript(String content, Compilable engine) throws ScriptException... |
355 |
|
{ |
356 |
|
|
357 |
|
|
358 |
0 |
return engine.compile(content); |
359 |
|
} |
360 |
|
} |