> converters = new HashMap<>();
+ converters.put(String.class, String::trim);
+ converters.put(Version.class, v -> new Version(v.trim()));
+ converters.put(Charset.class, v -> Charset.forName(v.trim()));
+ TYPE_CONVERTERS = Collections.unmodifiableMap(converters);
+ }
+
+ /**
+ * The base directory for reading template resources.
+ */
+ private String basePackage = "";
+
+ /**
+ * The default encoding for reading template resources.
+ */
+ private Charset defaultEncoding = StandardCharsets.UTF_8;
+
+ /**
+ * The incompatible improvements version of freemarker.
+ */
+ private Version incompatibleImprovementsVersion = Configuration.VERSION_2_3_22;
+
+ /**
+ * Get a base directory for reading template resources.
+ *
+ * Default is none (just under classpath).
+ *
+ *
+ * @return a base directory for reading template resources
+ */
+ public String getBasePackage() {
+ return basePackage;
+ }
+
+ /**
+ * Set a base directory for reading template resources.
+ *
+ * @param basePackage
+ * a base directory for reading template resources
+ */
+ public void setBasePackage(String basePackage) {
+ this.basePackage = basePackage;
+ }
+
+ /**
+ * Get a default encoding for reading template resources.
+ *
+ * Default is {@code UTF-8}.
+ *
+ *
+ * @return a default encoding for reading template resources
+ */
+ public Charset getDefaultEncoding() {
+ return defaultEncoding;
+ }
+
+ /**
+ * Set a default encoding for reading template resources.
+ *
+ * @param defaultEncoding
+ * a default encoding for reading template resources
+ */
+ public void setDefaultEncoding(Charset defaultEncoding) {
+ this.defaultEncoding = defaultEncoding;
+ }
+
+ /**
+ * Get an incompatible improvements version of freemarker.
+ *
+ * Default is 2.3.22.
+ *
+ *
+ * @return an incompatible improvements version of freemarker
+ */
+ public Version getIncompatibleImprovementsVersion() {
+ return incompatibleImprovementsVersion;
+ }
+
+ /**
+ * Set an incompatible improvements version of freemarker.
+ *
+ * @param incompatibleImprovementsVersion
+ * an incompatible improvements version of freemarker
+ */
+ public void setIncompatibleImprovementsVersion(Version incompatibleImprovementsVersion) {
+ this.incompatibleImprovementsVersion = incompatibleImprovementsVersion;
+ }
+
+ /**
+ * Create an instance from default properties file.
+ * If you want to customize a default {@code TemplateEngine}, you can configure some property using
+ * mybatis-freemarker.properties that encoded by UTF-8. Also, you can change the properties file that will read using
+ * system property (-Dmybatis-freemarker.config.file=... -Dmybatis-freemarker.config.encoding=...).
+ * Supported properties are as follows:
+ *
+ * Supported properties
+ *
+ * Property Key |
+ * Description |
+ * Default |
+ *
+ *
+ * General configuration |
+ *
+ *
+ * base-package |
+ * The base directory for reading template resources |
+ * None(just under classpath) |
+ *
+ *
+ * default-encoding |
+ * The default encoding for reading template resources |
+ * UTF-8 |
+ *
+ *
+ * freemarker-incompatible-improvements-version |
+ * The incompatible improvements version of freemarker |
+ * 2.3.22 |
+ *
+ *
+ *
+ * @return a configuration instance
+ */
+ public static FreeMarkerLanguageDriverConfig newInstance() {
+ return newInstance(loadDefaultProperties());
+ }
+
+ /**
+ * Create an instance from specified properties.
+ *
+ * @param customProperties
+ * custom configuration properties
+ * @return a configuration instance
+ * @see #newInstance()
+ */
+ public static FreeMarkerLanguageDriverConfig newInstance(Properties customProperties) {
+ FreeMarkerLanguageDriverConfig config = new FreeMarkerLanguageDriverConfig();
+ Properties properties = loadDefaultProperties();
+ Optional.ofNullable(customProperties).ifPresent(properties::putAll);
+ override(config, properties);
+ return config;
+ }
+
+ /**
+ * Create an instance using specified customizer and override using a default properties file.
+ *
+ * @param customizer
+ * baseline customizer
+ * @return a configuration instance
+ * @see #newInstance()
+ */
+ public static FreeMarkerLanguageDriverConfig newInstance(Consumer customizer) {
+ FreeMarkerLanguageDriverConfig config = new FreeMarkerLanguageDriverConfig();
+ customizer.accept(config);
+ override(config, loadDefaultProperties());
+ return config;
+ }
+
+ private static void override(FreeMarkerLanguageDriverConfig config, Properties properties) {
+ MetaObject metaObject = MetaObject.forObject(config, new DefaultObjectFactory(), new DefaultObjectWrapperFactory(),
+ new DefaultReflectorFactory());
+ properties.forEach((key, value) -> {
+ String propertyPath = WordUtils
+ .uncapitalize(WordUtils.capitalize(Objects.toString(key), '-').replaceAll("-", ""));
+ Optional.ofNullable(value).ifPresent(v -> {
+ Object convertedValue = TYPE_CONVERTERS.get(metaObject.getSetterType(propertyPath)).apply(value.toString());
+ metaObject.setValue(propertyPath, convertedValue);
+ });
+ });
+ }
+
+ private static Properties loadDefaultProperties() {
+ return loadProperties(System.getProperty(PROPERTY_KEY_CONFIG_FILE, DEFAULT_PROPERTIES_FILE));
+ }
+
+ private static Properties loadProperties(String resourcePath) {
+ Properties properties = new Properties();
+ InputStream in;
+ try {
+ in = Resources.getResourceAsStream(resourcePath);
+ } catch (IOException e) {
+ in = null;
+ }
+ if (in != null) {
+ Charset encoding = Optional.ofNullable(System.getProperty(PROPERTY_KEY_CONFIG_ENCODING)).map(Charset::forName)
+ .orElse(StandardCharsets.UTF_8);
+ try (InputStreamReader inReader = new InputStreamReader(in, encoding);
+ BufferedReader bufReader = new BufferedReader(inReader)) {
+ properties.load(bufReader);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ return properties;
+ }
+
+}
diff --git a/src/test/java/org/mybatis/scripting/freemarker/FreeMarkerLanguageDriverConfigTest.java b/src/test/java/org/mybatis/scripting/freemarker/FreeMarkerLanguageDriverConfigTest.java
new file mode 100644
index 0000000..5a3661f
--- /dev/null
+++ b/src/test/java/org/mybatis/scripting/freemarker/FreeMarkerLanguageDriverConfigTest.java
@@ -0,0 +1,103 @@
+/**
+ * Copyright 2015-2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.mybatis.scripting.freemarker;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.Properties;
+
+import freemarker.template.Configuration;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class FreeMarkerLanguageDriverConfigTest {
+
+ private String currentConfigFile;
+ private String currentConfigEncoding;
+
+ @BeforeEach
+ void saveCurrentConfig() {
+ currentConfigFile = System.getProperty("mybatis-freemarker.config");
+ currentConfigEncoding = System.getProperty("mybatis-freemarker.config.encoding");
+ }
+
+ @AfterEach
+ void restoreConfig() {
+ if (currentConfigFile == null) {
+ System.clearProperty("mybatis-freemarker.config.file");
+ } else {
+ System.setProperty("mybatis-freemarker.config.file", currentConfigFile);
+ }
+ if (currentConfigEncoding == null) {
+ System.clearProperty("mybatis-freemarker.config.encoding");
+ } else {
+ System.setProperty("mybatis-freemarker.config.encoding", currentConfigEncoding);
+ }
+ }
+
+ @Test
+ void newInstanceWithEmptyPropertiesFile() {
+ System.setProperty("mybatis-freemarker.config.file", "mybatis-freemarker-empty.properties");
+ FreeMarkerLanguageDriverConfig config = FreeMarkerLanguageDriverConfig.newInstance();
+ Assertions.assertEquals("", config.getBasePackage());
+ Assertions.assertEquals(StandardCharsets.UTF_8, config.getDefaultEncoding());
+ Assertions.assertEquals(Configuration.VERSION_2_3_22, config.getIncompatibleImprovementsVersion());
+ }
+
+ @Test
+ void newInstanceWithPropertiesFileNotFound() {
+ System.setProperty("mybatis-freemarker.config.file", "mybatis-freemarker-notfound.properties");
+ FreeMarkerLanguageDriverConfig config = FreeMarkerLanguageDriverConfig.newInstance();
+ Assertions.assertEquals("", config.getBasePackage());
+ Assertions.assertEquals(StandardCharsets.UTF_8, config.getDefaultEncoding());
+ Assertions.assertEquals(Configuration.VERSION_2_3_22, config.getIncompatibleImprovementsVersion());
+ }
+
+ @Test
+ void newInstanceWithCustomPropertiesFile() {
+ System.setProperty("mybatis-freemarker.config.file", "mybatis-freemarker-custom.properties");
+ FreeMarkerLanguageDriverConfig config = FreeMarkerLanguageDriverConfig.newInstance();
+ Assertions.assertEquals("sqls", config.getBasePackage());
+ Assertions.assertEquals(Charset.forName("Windows-31J"), config.getDefaultEncoding());
+ Assertions.assertEquals(Configuration.VERSION_2_3_28, config.getIncompatibleImprovementsVersion());
+ }
+
+ @Test
+ void newInstanceWithCustomProperties() {
+ Properties properties = new Properties();
+ properties.setProperty("defaultEncoding", " " + StandardCharsets.ISO_8859_1.name() + " ");
+ properties.setProperty("incompatibleImprovementsVersion", " 2.3.27 ");
+ FreeMarkerLanguageDriverConfig config = FreeMarkerLanguageDriverConfig.newInstance(properties);
+ Assertions.assertEquals("sql", config.getBasePackage());
+ Assertions.assertEquals(StandardCharsets.ISO_8859_1, config.getDefaultEncoding());
+ Assertions.assertEquals(Configuration.VERSION_2_3_27, config.getIncompatibleImprovementsVersion());
+ }
+
+ @Test
+ void newInstanceWithConsumer() {
+ FreeMarkerLanguageDriverConfig config = FreeMarkerLanguageDriverConfig.newInstance(c -> {
+ c.setBasePackage("sqls");
+ c.setDefaultEncoding(StandardCharsets.UTF_16);
+ c.setIncompatibleImprovementsVersion(Configuration.VERSION_2_3_26);
+ });
+ Assertions.assertEquals("sql", config.getBasePackage());
+ Assertions.assertEquals(StandardCharsets.UTF_16, config.getDefaultEncoding());
+ Assertions.assertEquals(Configuration.VERSION_2_3_26, config.getIncompatibleImprovementsVersion());
+ }
+
+}
diff --git a/src/test/resources/mybatis-freemarker-custom.properties b/src/test/resources/mybatis-freemarker-custom.properties
new file mode 100644
index 0000000..4ba41eb
--- /dev/null
+++ b/src/test/resources/mybatis-freemarker-custom.properties
@@ -0,0 +1,19 @@
+#
+# Copyright 2015-2019 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+base-package=sqls
+default-encoding=Windows-31J
+incompatible-improvements-version=2.3.28
\ No newline at end of file
diff --git a/src/test/resources/mybatis-freemarker-empty.properties b/src/test/resources/mybatis-freemarker-empty.properties
new file mode 100644
index 0000000..006c5da
--- /dev/null
+++ b/src/test/resources/mybatis-freemarker-empty.properties
@@ -0,0 +1,17 @@
+#
+# Copyright 2015-2019 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+#
diff --git a/src/test/resources/mybatis-freemarker.properties b/src/test/resources/mybatis-freemarker.properties
index accbc39..a3dfa2e 100644
--- a/src/test/resources/mybatis-freemarker.properties
+++ b/src/test/resources/mybatis-freemarker.properties
@@ -1,5 +1,5 @@
#
-# Copyright 2015-2016 the original author or authors.
+# Copyright 2015-2019 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -14,4 +14,4 @@
# limitations under the License.
#
-basePackage=sql
\ No newline at end of file
+basePackage=sql