1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mybatis.scripting.velocity;
17
18 import java.io.StringReader;
19 import java.io.StringWriter;
20 import java.util.HashMap;
21 import java.util.Map;
22 import java.util.Properties;
23 import java.util.stream.Collectors;
24
25 import org.apache.ibatis.builder.BuilderException;
26 import org.apache.ibatis.io.Resources;
27 import org.apache.ibatis.scripting.ScriptingException;
28 import org.apache.velocity.Template;
29 import org.apache.velocity.VelocityContext;
30 import org.apache.velocity.runtime.RuntimeConstants;
31 import org.apache.velocity.runtime.RuntimeInstance;
32 import org.apache.velocity.runtime.parser.node.SimpleNode;
33
34 public class VelocityFacade {
35
36 private static final RuntimeInstance engine = new RuntimeInstance();
37 private static final Map<String, Object> additionalCtxAttributes = new HashMap<>();
38
39 private VelocityFacade() {
40
41 }
42
43
44
45
46
47
48
49
50
51 public static void initialize(VelocityLanguageDriverConfig driverConfig) {
52 Properties properties = new Properties();
53 driverConfig.getVelocitySettings().forEach(properties::setProperty);
54 properties.setProperty(RuntimeConstants.CUSTOM_DIRECTIVES, driverConfig.generateCustomDirectivesString());
55 engine.init(properties);
56 additionalCtxAttributes.putAll(driverConfig.getAdditionalContextAttributes().entrySet().stream()
57 .collect(Collectors.toMap(Map.Entry::getKey, v -> {
58 try {
59 return Resources.classForName(v.getValue()).getConstructor().newInstance();
60 } catch (Exception e) {
61 throw new ScriptingException("Cannot load additional context attribute class.", e);
62 }
63 })));
64 }
65
66
67
68
69
70
71 public static void destroy() {
72 engine.reset();
73 additionalCtxAttributes.clear();
74 }
75
76 public static Object compile(String script, String name) {
77 try {
78 StringReader reader = new StringReader(script);
79 Template template = new Template();
80 SimpleNode node = engine.parse(reader, template);
81 template.setRuntimeServices(engine);
82 template.setData(node);
83 template.setName(name);
84 template.initDocument();
85 return template;
86 } catch (Exception ex) {
87 throw new BuilderException("Error parsing velocity script '" + name + "'", ex);
88 }
89 }
90
91 public static String apply(Object template, Map<String, Object> context) {
92 final StringWriter out = new StringWriter();
93 context.putAll(additionalCtxAttributes);
94 ((Template) template).merge(new VelocityContext(context), out);
95 return out.toString();
96 }
97
98 }