1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mybatis.scripting.freemarker;
17
18 import java.io.IOException;
19 import java.io.StringReader;
20 import java.nio.charset.StandardCharsets;
21
22 import org.apache.ibatis.executor.parameter.ParameterHandler;
23 import org.apache.ibatis.mapping.BoundSql;
24 import org.apache.ibatis.mapping.MappedStatement;
25 import org.apache.ibatis.mapping.SqlSource;
26 import org.apache.ibatis.parsing.XNode;
27 import org.apache.ibatis.scripting.LanguageDriver;
28 import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
29 import org.apache.ibatis.session.Configuration;
30 import org.mybatis.scripting.freemarker.support.TemplateFilePathProvider;
31
32 import freemarker.cache.ClassTemplateLoader;
33 import freemarker.cache.TemplateLoader;
34 import freemarker.template.Template;
35 import freemarker.template.TemplateException;
36
37
38
39
40
41
42
43
44 public class FreeMarkerLanguageDriver implements LanguageDriver {
45
46 protected final FreeMarkerLanguageDriverConfig driverConfig;
47 protected final freemarker.template.Configuration freemarkerCfg;
48
49
50
51
52
53
54 public FreeMarkerLanguageDriver() {
55 this(FreeMarkerLanguageDriverConfig.newInstance());
56 }
57
58
59
60
61
62
63
64
65
66 public FreeMarkerLanguageDriver(FreeMarkerLanguageDriverConfig driverConfig) {
67 this.driverConfig = driverConfig;
68 this.freemarkerCfg = createFreeMarkerConfiguration();
69 TemplateFilePathProvider.setLanguageDriverConfig(driverConfig);
70 }
71
72
73
74
75
76 protected freemarker.template.Configuration createFreeMarkerConfiguration() {
77 freemarker.template.Configuration cfg = new freemarker.template.Configuration(
78 freemarker.template.Configuration.VERSION_2_3_22);
79
80 TemplateLoader templateLoader = new ClassTemplateLoader(this.getClass().getClassLoader(),
81 driverConfig.getTemplateFile().getBaseDir());
82 cfg.setTemplateLoader(templateLoader);
83
84
85 cfg.setNumberFormat("computer");
86
87
88 cfg.setDefaultEncoding(StandardCharsets.UTF_8.name());
89
90 driverConfig.getFreemarkerSettings().forEach((name, value) -> {
91 try {
92 cfg.setSetting(name, value);
93 } catch (TemplateException e) {
94 throw new IllegalStateException(
95 String.format("Fail to configure FreeMarker template setting. name[%s] value[%s]", name, value), e);
96 }
97 });
98
99 return cfg;
100 }
101
102
103
104
105
106
107
108
109
110
111
112
113
114 @Override
115 public ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject,
116 BoundSql boundSql) {
117
118 return new DefaultParameterHandler(mappedStatement, parameterObject, boundSql);
119 }
120
121
122
123
124
125
126
127
128
129
130
131
132
133 @Override
134 public SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType) {
135 try {
136 return createSqlSource(configuration, script.getNode().getTextContent());
137 } catch (IOException e) {
138 throw new RuntimeException(e);
139 }
140 }
141
142
143
144
145
146
147
148
149
150
151
152
153
154 @Override
155 public SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType) {
156 try {
157 return createSqlSource(configuration, script);
158 } catch (IOException e) {
159 throw new RuntimeException(e);
160 }
161 }
162
163 protected SqlSource createSqlSource(Template template, Configuration configuration) {
164 return new FreeMarkerSqlSource(template, configuration, freemarkerCfg.getIncompatibleImprovements());
165 }
166
167 protected SqlSource createSqlSource(Configuration configuration, String scriptText) throws IOException {
168 Template template;
169 if (scriptText.trim().contains(" ")) {
170
171 template = new Template(null, new StringReader(scriptText), freemarkerCfg);
172 } else {
173
174 template = freemarkerCfg.getTemplate(scriptText.trim());
175 }
176
177 return createSqlSource(template, configuration);
178 }
179
180 }