1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mybatis.spring.boot.autoconfigure;
17
18 import static org.assertj.core.api.Assertions.assertThat;
19
20 import java.io.IOException;
21 import java.io.Writer;
22 import java.nio.charset.Charset;
23 import java.nio.charset.StandardCharsets;
24 import java.util.Map;
25
26 import org.apache.ibatis.mapping.BoundSql;
27 import org.apache.ibatis.mapping.SqlSource;
28 import org.apache.ibatis.scripting.LanguageDriver;
29 import org.apache.ibatis.session.Configuration;
30 import org.apache.velocity.context.InternalContextAdapter;
31 import org.apache.velocity.exception.MethodInvocationException;
32 import org.apache.velocity.exception.ParseErrorException;
33 import org.apache.velocity.exception.ResourceNotFoundException;
34 import org.apache.velocity.runtime.RuntimeConstants;
35 import org.apache.velocity.runtime.directive.Directive;
36 import org.apache.velocity.runtime.parser.node.Node;
37 import org.junit.jupiter.api.AfterEach;
38 import org.junit.jupiter.api.BeforeEach;
39 import org.junit.jupiter.api.Test;
40 import org.mybatis.scripting.freemarker.FreeMarkerLanguageDriver;
41 import org.mybatis.scripting.freemarker.FreeMarkerLanguageDriverConfig;
42 import org.mybatis.scripting.thymeleaf.TemplateEngineCustomizer;
43 import org.mybatis.scripting.thymeleaf.ThymeleafLanguageDriver;
44 import org.mybatis.scripting.thymeleaf.ThymeleafLanguageDriverConfig;
45 import org.mybatis.scripting.velocity.VelocityFacade;
46 import org.mybatis.scripting.velocity.VelocityLanguageDriver;
47 import org.mybatis.scripting.velocity.VelocityLanguageDriverConfig;
48 import org.springframework.boot.autoconfigure.AutoConfigurations;
49 import org.springframework.boot.context.properties.EnableConfigurationProperties;
50 import org.springframework.boot.test.context.runner.ApplicationContextRunner;
51 import org.springframework.context.annotation.Bean;
52 import org.thymeleaf.TemplateEngine;
53
54
55
56
57
58
59
60 class MybatisLanguageDriverAutoConfigurationTest {
61
62 private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
63 .withConfiguration(AutoConfigurations.of(MybatisLanguageDriverAutoConfiguration.class));
64
65 @BeforeEach
66 @AfterEach
67 void initializeVelocity() {
68 VelocityFacade.destroy();
69 }
70
71 @Test
72 void testDefaultConfiguration() {
73 this.contextRunner.run(context -> {
74 Map<String, LanguageDriver> languageDriverBeans = context.getBeansOfType(LanguageDriver.class);
75 assertThat(languageDriverBeans).hasSize(3).containsKeys("freeMarkerLanguageDriver", "velocityLanguageDriver",
76 "thymeleafLanguageDriver");
77 assertThat(languageDriverBeans.get("freeMarkerLanguageDriver")).isInstanceOf(FreeMarkerLanguageDriver.class);
78 assertThat(languageDriverBeans.get("velocityLanguageDriver")).isInstanceOf(VelocityLanguageDriver.class);
79 assertThat(languageDriverBeans.get("thymeleafLanguageDriver")).isInstanceOf(ThymeleafLanguageDriver.class);
80
81 ThymeleafLanguageDriverConfig thymeleafLanguageDriverConfig = context
82 .getBean(ThymeleafLanguageDriverConfig.class);
83 assertThat(thymeleafLanguageDriverConfig.isUse2way()).isTrue();
84 assertThat(thymeleafLanguageDriverConfig.getDialect().getPrefix()).isEqualTo("mb");
85 assertThat(thymeleafLanguageDriverConfig.getDialect().getLikeAdditionalEscapeTargetChars()).isNull();
86 assertThat(thymeleafLanguageDriverConfig.getDialect().getLikeEscapeChar()).isEqualTo('\\');
87 assertThat(thymeleafLanguageDriverConfig.getDialect().getLikeEscapeClauseFormat()).isEqualTo("ESCAPE '%s'");
88 assertThat(thymeleafLanguageDriverConfig.getTemplateFile().getBaseDir()).isEmpty();
89 assertThat(thymeleafLanguageDriverConfig.getTemplateFile().getCacheTtl()).isNull();
90 assertThat(thymeleafLanguageDriverConfig.getTemplateFile().getEncoding()).isEqualTo(StandardCharsets.UTF_8);
91 assertThat(thymeleafLanguageDriverConfig.getTemplateFile().getPatterns()).hasSize(1).contains("*.sql");
92 assertThat(thymeleafLanguageDriverConfig.getCustomizer()).isNull();
93
94 FreeMarkerLanguageDriverConfig freeMarkerLanguageDriverConfig = context
95 .getBean(FreeMarkerLanguageDriverConfig.class);
96 assertThat(freeMarkerLanguageDriverConfig.getBasePackage()).isEmpty();
97 assertThat(freeMarkerLanguageDriverConfig.getFreemarkerSettings()).isEmpty();
98
99 VelocityLanguageDriverConfig velocityLanguageDriverConfig = context.getBean(VelocityLanguageDriverConfig.class);
100 @SuppressWarnings("deprecation")
101 String[] userDirective = velocityLanguageDriverConfig.getUserdirective();
102 assertThat(userDirective).isEmpty();
103 assertThat(velocityLanguageDriverConfig.getAdditionalContextAttributes()).isEmpty();
104 assertThat(velocityLanguageDriverConfig.getVelocitySettings()).hasSize(2);
105 assertThat(velocityLanguageDriverConfig.getVelocitySettings()).containsEntry(RuntimeConstants.RESOURCE_LOADERS,
106 "class");
107 assertThat(velocityLanguageDriverConfig.getVelocitySettings()).containsEntry(
108 RuntimeConstants.RESOURCE_LOADER + ".class.class",
109 "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
110 assertThat(velocityLanguageDriverConfig.generateCustomDirectivesString()).isEqualTo(
111 "org.mybatis.scripting.velocity.TrimDirective,org.mybatis.scripting.velocity.WhereDirective,org.mybatis.scripting.velocity.SetDirective,org.mybatis.scripting.velocity.InDirective,org.mybatis.scripting.velocity.RepeatDirective");
112 });
113 }
114
115 @Test
116 void testCustomConfiguration() {
117 this.contextRunner.withUserConfiguration(MyLanguageDriverConfig.class).run(context -> {
118 Map<String, LanguageDriver> languageDriverBeans = context.getBeansOfType(LanguageDriver.class);
119 assertThat(languageDriverBeans).hasSize(3).containsKeys("myFreeMarkerLanguageDriver", "myVelocityLanguageDriver",
120 "myThymeleafLanguageDriver");
121 });
122 }
123
124 @Test
125 @SuppressWarnings("deprecation")
126 void testLegacyConfiguration() {
127 new ApplicationContextRunner()
128 .withUserConfiguration(TestingLegacyFreeMarkerConfiguration.class, TestingLegacyVelocityConfiguration.class)
129 .run(context -> {
130 Map<String, LanguageDriver> languageDriverBeans = context.getBeansOfType(LanguageDriver.class);
131 assertThat(languageDriverBeans).hasSize(2).containsKeys("freeMarkerLanguageDriver", "velocityLanguageDriver");
132 assertThat(context.getBean(org.mybatis.scripting.velocity.Driver.class)).isNotNull();
133 assertThat(context.getBean(FreeMarkerLanguageDriver.class)).isNotNull();
134 assertThat(context.getBeanNamesForType(VelocityLanguageDriverConfig.class)).isEmpty();
135 assertThat(context.getBeanNamesForType(FreeMarkerLanguageDriverConfig.class)).isEmpty();
136 });
137 }
138
139 @Test
140 void testCustomThymeleafConfig() {
141 this.contextRunner.withUserConfiguration(ThymeleafCustomLanguageDriverConfig.class).run(context -> {
142 ThymeleafLanguageDriver driver = context.getBean(ThymeleafLanguageDriver.class);
143 SqlSource sqlSource = driver.createSqlSource(new Configuration(),
144 "SELECT * FROM users WHERE id = /*[# m:p='id']*/ 1 /*[/]*/", Integer.class);
145 BoundSql boundSql = sqlSource.getBoundSql(10);
146 assertThat(boundSql.getSql()).isEqualTo("SELECT * FROM users WHERE id = ?");
147 assertThat(boundSql.getParameterObject()).isEqualTo(10);
148 assertThat(boundSql.getParameterMappings().get(0).getProperty()).isEqualTo("id");
149 assertThat(boundSql.getParameterMappings().get(0).getJavaType()).isEqualTo(Integer.class);
150 ThymeleafLanguageDriverConfig config = context.getBean(ThymeleafLanguageDriverConfig.class);
151 assertThat(config.isUse2way()).isTrue();
152 assertThat(config.getDialect().getPrefix()).isEqualTo("m");
153 assertThat(config.getDialect().getLikeAdditionalEscapeTargetChars()).isNull();
154 assertThat(config.getDialect().getLikeEscapeChar()).isEqualTo('\\');
155 assertThat(config.getDialect().getLikeEscapeClauseFormat()).isEqualTo("ESCAPE '%s'");
156 assertThat(config.getTemplateFile().getBaseDir()).isEmpty();
157 assertThat(config.getTemplateFile().getCacheTtl()).isNull();
158 assertThat(config.getTemplateFile().getEncoding()).isEqualTo(StandardCharsets.UTF_8);
159 assertThat(config.getTemplateFile().getPatterns()).hasSize(1).contains("*.sql");
160 assertThat(config.getCustomizer()).isNull();
161 });
162 }
163
164 @Test
165 void testCustomFreeMarkerConfig() {
166 this.contextRunner.withUserConfiguration(FreeMarkerCustomLanguageDriverConfig.class).run(context -> {
167 FreeMarkerLanguageDriver driver = context.getBean(FreeMarkerLanguageDriver.class);
168 @SuppressWarnings("unused")
169 class Param {
170 private Integer id;
171 private Integer version;
172 }
173 Param params = new Param();
174 params.id = 10;
175 params.version = 20;
176 SqlSource sqlSource = driver.createSqlSource(new Configuration(),
177 "SELECT * FROM users WHERE id = #{id} and version = <@p name='version'/>", Param.class);
178 BoundSql boundSql = sqlSource.getBoundSql(params);
179 assertThat(boundSql.getSql()).isEqualTo("SELECT * FROM users WHERE id = ? and version = ?");
180 assertThat(boundSql.getParameterMappings().get(0).getProperty()).isEqualTo("id");
181 assertThat(boundSql.getParameterMappings().get(0).getJavaType()).isEqualTo(Integer.class);
182 assertThat(boundSql.getParameterMappings().get(1).getProperty()).isEqualTo("version");
183 assertThat(boundSql.getParameterMappings().get(1).getJavaType()).isEqualTo(Integer.class);
184 FreeMarkerLanguageDriverConfig config = context.getBean(FreeMarkerLanguageDriverConfig.class);
185 assertThat(config.getBasePackage()).isEmpty();
186 assertThat(config.getFreemarkerSettings()).hasSize(1);
187 assertThat(config.getFreemarkerSettings()).containsEntry("interpolation_syntax", "dollar");
188 });
189 }
190
191 @Test
192 void testCustomVelocityConfig() {
193 this.contextRunner.withUserConfiguration(VelocityCustomLanguageDriverConfig.class).run(context -> {
194 VelocityLanguageDriver driver = context.getBean(VelocityLanguageDriver.class);
195 @SuppressWarnings("unused")
196 class Param {
197 private Integer id;
198 private Integer version;
199 }
200 Param params = new Param();
201 params.id = 10;
202 params.version = 20;
203 SqlSource sqlSource = driver.createSqlSource(new Configuration(), "#now()", Param.class);
204 BoundSql boundSql = sqlSource.getBoundSql(params);
205 assertThat(boundSql.getSql()).isEqualTo("SELECT CURRENT_TIMESTAMP");
206 VelocityLanguageDriverConfig config = context.getBean(VelocityLanguageDriverConfig.class);
207 @SuppressWarnings("deprecation")
208 String[] userDirective = config.getUserdirective();
209 assertThat(userDirective).isEmpty();
210 assertThat(config.getAdditionalContextAttributes()).isEmpty();
211 assertThat(config.getVelocitySettings()).hasSize(3);
212 assertThat(config.getVelocitySettings()).containsEntry(RuntimeConstants.RESOURCE_LOADERS, "class");
213 assertThat(config.getVelocitySettings()).containsEntry(RuntimeConstants.RESOURCE_LOADER + ".class.class",
214 "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
215 assertThat(config.generateCustomDirectivesString()).isEqualTo(NowDirective.class.getName()
216 + ",org.mybatis.scripting.velocity.TrimDirective,org.mybatis.scripting.velocity.WhereDirective,org.mybatis.scripting.velocity.SetDirective,org.mybatis.scripting.velocity.InDirective,org.mybatis.scripting.velocity.RepeatDirective");
217 });
218 }
219
220 @Test
221 void testCustomThymeleafConfigUsingConfigurationProperty() {
222 this.contextRunner.withUserConfiguration(MyAutoConfiguration.class).withPropertyValues(
223 "mybatis.scripting-language-driver.thymeleaf.use2way=false",
224 "mybatis.scripting-language-driver.thymeleaf.dialect.like-additional-escape-target-chars=*,?",
225 "mybatis.scripting-language-driver.thymeleaf.dialect.like-escape-char=~",
226 "mybatis.scripting-language-driver.thymeleaf.dialect.like-escape-clause-format=escape '%s'",
227 "mybatis.scripting-language-driver.thymeleaf.dialect.prefix=mybatis",
228 "mybatis.scripting-language-driver.thymeleaf.template-file.base-dir=sqls",
229 "mybatis.scripting-language-driver.thymeleaf.template-file.cache-enabled=false",
230 "mybatis.scripting-language-driver.thymeleaf.template-file.cache-ttl=1234",
231 "mybatis.scripting-language-driver.thymeleaf.template-file.encoding=Windows-31J",
232 "mybatis.scripting-language-driver.thymeleaf.template-file.patterns=*.sql,*.sqlf",
233 "mybatis.scripting-language-driver.thymeleaf.template-file.path-provider.prefix=sql/",
234 "mybatis.scripting-language-driver.thymeleaf.template-file.path-provider.includes-package-path=false",
235 "mybatis.scripting-language-driver.thymeleaf.template-file.path-provider.separate-directory-per-mapper=false",
236 "mybatis.scripting-language-driver.thymeleaf.template-file.path-provider.includes-mapper-name-when-separate-directory=false",
237 "mybatis.scripting-language-driver.thymeleaf.template-file.path-provider.cache-enabled=false",
238 "mybatis.scripting-language-driver.thymeleaf.customizer=org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfigurationTest$MyTemplateEngineCustomizer")
239 .run(context -> {
240 ThymeleafLanguageDriver driver = context.getBean(ThymeleafLanguageDriver.class);
241 SqlSource sqlSource = driver.createSqlSource(new Configuration(),
242 "SELECT * FROM users WHERE id = [# mybatis:p='id' /]", Integer.class);
243 BoundSql boundSql = sqlSource.getBoundSql(10);
244 assertThat(boundSql.getSql()).isEqualTo("SELECT * FROM users WHERE id = ?");
245 assertThat(boundSql.getParameterObject()).isEqualTo(10);
246 assertThat(boundSql.getParameterMappings().get(0).getProperty()).isEqualTo("id");
247 assertThat(boundSql.getParameterMappings().get(0).getJavaType()).isEqualTo(Integer.class);
248 ThymeleafLanguageDriverConfig config = context.getBean(ThymeleafLanguageDriverConfig.class);
249 assertThat(config.isUse2way()).isFalse();
250 assertThat(config.getDialect().getPrefix()).isEqualTo("mybatis");
251 assertThat(config.getDialect().getLikeAdditionalEscapeTargetChars()).hasSize(2).contains('*', '?');
252 assertThat(config.getDialect().getLikeEscapeChar()).isEqualTo('~');
253 assertThat(config.getDialect().getLikeEscapeClauseFormat()).isEqualTo("escape '%s'");
254 assertThat(config.getTemplateFile().getBaseDir()).isEqualTo("sqls");
255 assertThat(config.getTemplateFile().getCacheTtl()).isEqualTo(1234);
256 assertThat(config.getTemplateFile().getEncoding()).isEqualTo(Charset.forName("Windows-31J"));
257 assertThat(config.getTemplateFile().getPatterns()).hasSize(2).contains("*.sql", "*.sqlf");
258 assertThat(config.getTemplateFile().getPathProvider().getPrefix()).isEqualTo("sql/");
259 assertThat(config.getTemplateFile().getPathProvider().isIncludesPackagePath()).isFalse();
260 assertThat(config.getTemplateFile().getPathProvider().isSeparateDirectoryPerMapper()).isFalse();
261 assertThat(config.getTemplateFile().getPathProvider().isIncludesMapperNameWhenSeparateDirectory()).isFalse();
262 assertThat(config.getTemplateFile().getPathProvider().isCacheEnabled()).isFalse();
263 assertThat(config.getCustomizer()).isEqualTo(MyTemplateEngineCustomizer.class);
264 });
265 }
266
267 @Test
268 void testCustomFreeMarkerConfigUsingConfigurationProperty() {
269 this.contextRunner.withUserConfiguration(MyAutoConfiguration.class)
270 .withPropertyValues("mybatis.scripting-language-driver.freemarker.base-package=sqls",
271 "mybatis.scripting-language-driver.freemarker.freemarker-settings.interpolation_syntax=dollar",
272 "mybatis.scripting-language-driver.freemarker.freemarker-settings.whitespace_stripping=yes")
273 .run(context -> {
274 FreeMarkerLanguageDriver driver = context.getBean(FreeMarkerLanguageDriver.class);
275 @SuppressWarnings("unused")
276 class Param {
277 private Integer id;
278 private Integer version;
279 }
280 Param params = new Param();
281 params.id = 10;
282 params.version = 20;
283 SqlSource sqlSource = driver.createSqlSource(new Configuration(),
284 "SELECT * FROM users WHERE id = #{id} and version = <@p name='version'/>", Param.class);
285 BoundSql boundSql = sqlSource.getBoundSql(params);
286 assertThat(boundSql.getSql()).isEqualTo("SELECT * FROM users WHERE id = ? and version = ?");
287 assertThat(boundSql.getParameterMappings().get(0).getProperty()).isEqualTo("id");
288 assertThat(boundSql.getParameterMappings().get(0).getJavaType()).isEqualTo(Integer.class);
289 assertThat(boundSql.getParameterMappings().get(1).getProperty()).isEqualTo("version");
290 assertThat(boundSql.getParameterMappings().get(1).getJavaType()).isEqualTo(Integer.class);
291 FreeMarkerLanguageDriverConfig config = context.getBean(FreeMarkerLanguageDriverConfig.class);
292 assertThat(config.getBasePackage()).isEqualTo("sqls");
293 assertThat(config.getFreemarkerSettings()).hasSize(2);
294 assertThat(config.getFreemarkerSettings()).containsEntry("interpolation_syntax", "dollar");
295 assertThat(config.getFreemarkerSettings()).containsEntry("whitespace_stripping", "yes");
296 });
297 }
298
299 @Test
300 void testCustomVelocityConfigUsingConfigurationProperty() {
301 this.contextRunner.withUserConfiguration(MyAutoConfiguration.class)
302 .withPropertyValues("mybatis.scripting-language-driver.velocity.userdirective=" + NowDirective.class.getName(),
303 "mybatis.scripting-language-driver.velocity.velocity-settings." + RuntimeConstants.INPUT_ENCODING + "="
304 + RuntimeConstants.ENCODING_DEFAULT,
305 "mybatis.scripting-language-driver.velocity.additional-context-attributes.attribute1=java.lang.String",
306 "mybatis.scripting-language-driver.velocity.additional-context-attributes.attribute2=java.util.HashMap")
307 .run(context -> {
308 VelocityLanguageDriver driver = context.getBean(VelocityLanguageDriver.class);
309 @SuppressWarnings("unused")
310 class Param {
311 private Integer id;
312 private Integer version;
313 }
314 Param params = new Param();
315 params.id = 10;
316 params.version = 20;
317 SqlSource sqlSource = driver.createSqlSource(new Configuration(), "#now()", Param.class);
318 BoundSql boundSql = sqlSource.getBoundSql(params);
319 assertThat(boundSql.getSql()).isEqualTo("SELECT CURRENT_TIMESTAMP");
320 VelocityLanguageDriverConfig config = context.getBean(VelocityLanguageDriverConfig.class);
321 @SuppressWarnings("deprecation")
322 String[] userDirective = config.getUserdirective();
323 assertThat(userDirective).hasSize(1).contains(NowDirective.class.getName());
324 assertThat(config.getAdditionalContextAttributes()).hasSize(2);
325 assertThat(config.getAdditionalContextAttributes()).containsEntry("attribute1", "java.lang.String");
326 assertThat(config.getAdditionalContextAttributes()).containsEntry("attribute2", "java.util.HashMap");
327 assertThat(config.getVelocitySettings()).hasSize(3);
328 assertThat(config.getVelocitySettings()).containsEntry(RuntimeConstants.RESOURCE_LOADERS, "class");
329 assertThat(config.getVelocitySettings()).containsEntry(RuntimeConstants.RESOURCE_LOADER + ".class.class",
330 "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
331 assertThat(config.generateCustomDirectivesString()).isEqualTo(NowDirective.class.getName()
332 + ",org.mybatis.scripting.velocity.TrimDirective,org.mybatis.scripting.velocity.WhereDirective,org.mybatis.scripting.velocity.SetDirective,org.mybatis.scripting.velocity.InDirective,org.mybatis.scripting.velocity.RepeatDirective");
333 assertThat(config.getVelocitySettings()).containsEntry(RuntimeConstants.INPUT_ENCODING,
334 RuntimeConstants.ENCODING_DEFAULT);
335 });
336 }
337
338 @Test
339 void testExcludeMybatisLanguageDriverAutoConfiguration() {
340 new ApplicationContextRunner().withUserConfiguration(MyAutoConfiguration.class)
341 .run(context -> assertThat(context.getBeanNamesForType(LanguageDriver.class)).isEmpty());
342 }
343
344 @EnableConfigurationProperties
345 static class MyAutoConfiguration {
346 }
347
348 @org.springframework.context.annotation.Configuration
349 static class TestingLegacyFreeMarkerConfiguration
350 extends MybatisLanguageDriverAutoConfiguration.LegacyFreeMarkerConfiguration {
351 }
352
353 @org.springframework.context.annotation.Configuration
354 static class TestingLegacyVelocityConfiguration
355 extends MybatisLanguageDriverAutoConfiguration.LegacyVelocityConfiguration {
356 }
357
358 @org.springframework.context.annotation.Configuration
359 static class MyLanguageDriverConfig {
360 @Bean
361 FreeMarkerLanguageDriver myFreeMarkerLanguageDriver() {
362 return new FreeMarkerLanguageDriver();
363 }
364
365 @Bean
366 VelocityLanguageDriver myVelocityLanguageDriver() {
367 return new VelocityLanguageDriver();
368 }
369
370 @Bean
371 ThymeleafLanguageDriver myThymeleafLanguageDriver() {
372 return new ThymeleafLanguageDriver();
373 }
374 }
375
376 @org.springframework.context.annotation.Configuration
377 static class ThymeleafCustomLanguageDriverConfig {
378 @Bean
379 ThymeleafLanguageDriverConfig thymeleafLanguageDriverConfig() {
380 return ThymeleafLanguageDriverConfig.newInstance(c -> c.getDialect().setPrefix("m"));
381 }
382 }
383
384 @org.springframework.context.annotation.Configuration
385 static class FreeMarkerCustomLanguageDriverConfig {
386 @Bean
387 FreeMarkerLanguageDriverConfig freeMarkerLanguageDriverConfig() {
388 return FreeMarkerLanguageDriverConfig
389 .newInstance(c -> c.getFreemarkerSettings().put("interpolation_syntax", "dollar"));
390 }
391 }
392
393 @org.springframework.context.annotation.Configuration
394 static class VelocityCustomLanguageDriverConfig {
395 @Bean
396 VelocityLanguageDriverConfig velocityLanguageDriverConfig() {
397 return VelocityLanguageDriverConfig.newInstance(
398 c -> c.getVelocitySettings().put(RuntimeConstants.CUSTOM_DIRECTIVES, NowDirective.class.getName()));
399 }
400 }
401
402 public static class MyTemplateEngineCustomizer implements TemplateEngineCustomizer {
403 @Override
404 public void customize(TemplateEngine defaultTemplateEngine) {
405 }
406 }
407
408 public static class NowDirective extends Directive {
409
410 @Override
411 public String getName() {
412 return "now";
413 }
414
415 @Override
416 public int getType() {
417 return LINE;
418 }
419
420 @Override
421 public boolean render(InternalContextAdapter context, Writer writer, Node node)
422 throws IOException, ResourceNotFoundException, ParseErrorException, MethodInvocationException {
423 writer.append("SELECT CURRENT_TIMESTAMP");
424 return true;
425 }
426
427 }
428 }