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 return createSqlSource(configuration, script.getNode().getTextContent());
136 }
137
138
139
140
141
142
143
144
145
146
147
148
149
150 @Override
151 public SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType) {
152 return createSqlSource(configuration, script);
153 }
154
155 protected SqlSource createSqlSource(Template template, Configuration configuration) {
156 return new FreeMarkerSqlSource(template, configuration, freemarkerCfg.getIncompatibleImprovements());
157 }
158
159 private SqlSource createSqlSource(Configuration configuration, String scriptText) {
160 Template template;
161 if (scriptText.trim().contains(" ")) {
162
163 try {
164 template = new Template(null, new StringReader(scriptText), freemarkerCfg);
165 } catch (IOException e) {
166 throw new RuntimeException(e);
167 }
168 } else {
169
170 try {
171 template = freemarkerCfg.getTemplate(scriptText.trim());
172 } catch (IOException e) {
173 throw new RuntimeException(e);
174 }
175 }
176
177 return createSqlSource(template, configuration);
178 }
179
180 }