You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2017/03/28 23:10:31 UTC

[1/2] incubator-freemarker git commit: Settings that have contained a charset name (sourceEncoding, outputEncoding, URLEscapingCharset) are now of type Charset, not String. For string based configuration sources (such as .properties files) this means tha

Repository: incubator-freemarker
Updated Branches:
  refs/heads/3 5062b4ebf -> 27a62ce01


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/java/org/apache/freemarker/core/ConfigurationTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/core/ConfigurationTest.java b/src/test/java/org/apache/freemarker/core/ConfigurationTest.java
index c62b078..55a40d0 100644
--- a/src/test/java/org/apache/freemarker/core/ConfigurationTest.java
+++ b/src/test/java/org/apache/freemarker/core/ConfigurationTest.java
@@ -27,6 +27,7 @@ import java.io.IOException;
 import java.io.Serializable;
 import java.io.StringWriter;
 import java.lang.reflect.Field;
+import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -88,6 +89,8 @@ import junit.framework.TestCase;
 
 public class ConfigurationTest extends TestCase {
 
+    private static final Charset ISO_8859_2 = Charset.forName("ISO-8859-2");
+
     public ConfigurationTest(String name) {
         super(name);
     }
@@ -248,21 +251,18 @@ public class ConfigurationTest extends TestCase {
     @SuppressWarnings("boxing")
     public void testGetTemplateOverloads() throws Exception {
         final Locale hu = new Locale("hu", "HU");
-        final String latin1 = "ISO-8859-1";
-        final String latin2 = "ISO-8859-2";
-        final String utf8 = "utf-8";
         final String tFtl = "t.ftl";
         final String tHuFtl = "t_hu.ftl";
         final String tEnFtl = "t_en.ftl";
-        final String tUtf8Ftl = "t-utf8.ftl";
+        final String tUtf8Ftl = "utf8.ftl";
         final Serializable custLookupCond = new Serializable() { };
         
         Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
         cfg.setLocale(Locale.GERMAN);
-        cfg.setEncoding(latin1);
+        cfg.setSourceEncoding(StandardCharsets.ISO_8859_1);
 
         TemplateConfiguration huTC = new TemplateConfiguration();
-        huTC.setSourceEncoding(latin2);
+        huTC.setSourceEncoding(ISO_8859_2);
         cfg.setTemplateConfigurations(
                 new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*_hu.*"),
                 huTC));
@@ -281,7 +281,7 @@ public class ConfigurationTest extends TestCase {
             assertEquals(tFtl, t.getSourceName());
             assertEquals(Locale.GERMAN, t.getLocale());
             assertNull(t.getCustomLookupCondition());
-            assertEquals(latin1, t.getSourceEncoding());
+            assertEquals(StandardCharsets.ISO_8859_1, t.getSourceEncoding());
         }
         {
             Template t = cfg.getTemplate(tUtf8Ftl);
@@ -289,7 +289,7 @@ public class ConfigurationTest extends TestCase {
             assertEquals(tUtf8Ftl, t.getSourceName());
             assertEquals(Locale.GERMAN, t.getLocale());
             assertNull(t.getCustomLookupCondition());
-            assertEquals(utf8, t.getSourceEncoding());
+            assertEquals(StandardCharsets.UTF_8, t.getSourceEncoding());
         }
         
         // 2 args:
@@ -299,7 +299,7 @@ public class ConfigurationTest extends TestCase {
             assertEquals(tFtl, t.getSourceName());
             assertEquals(Locale.GERMAN, t.getLocale());
             assertNull(t.getCustomLookupCondition());
-            assertEquals(latin1, t.getSourceEncoding());
+            assertEquals(StandardCharsets.ISO_8859_1, t.getSourceEncoding());
         }
         {
             Template t = cfg.getTemplate(tFtl, (Locale) null);
@@ -307,7 +307,7 @@ public class ConfigurationTest extends TestCase {
             assertEquals(tFtl, t.getSourceName());
             assertEquals(Locale.GERMAN, t.getLocale());
             assertNull(t.getCustomLookupCondition());
-            assertEquals(latin1, t.getSourceEncoding());
+            assertEquals(StandardCharsets.ISO_8859_1, t.getSourceEncoding());
         }
         {
             Template t = cfg.getTemplate(tFtl, Locale.US);
@@ -315,7 +315,7 @@ public class ConfigurationTest extends TestCase {
             assertEquals(tEnFtl, t.getSourceName());
             assertEquals(Locale.US, t.getLocale());
             assertNull(t.getCustomLookupCondition());
-            assertEquals(latin1, t.getSourceEncoding());
+            assertEquals(StandardCharsets.ISO_8859_1, t.getSourceEncoding());
         }
         {
             Template t = cfg.getTemplate(tUtf8Ftl, Locale.US);
@@ -323,7 +323,7 @@ public class ConfigurationTest extends TestCase {
             assertEquals(tUtf8Ftl, t.getSourceName());
             assertEquals(Locale.US, t.getLocale());
             assertNull(t.getCustomLookupCondition());
-            assertEquals(utf8, t.getSourceEncoding());
+            assertEquals(StandardCharsets.UTF_8, t.getSourceEncoding());
         }
         {
             Template t = cfg.getTemplate(tFtl, hu);
@@ -331,7 +331,7 @@ public class ConfigurationTest extends TestCase {
             assertEquals(tHuFtl, t.getSourceName());
             assertEquals(hu, t.getLocale());
             assertNull(t.getCustomLookupCondition());
-            assertEquals(latin2, t.getSourceEncoding());
+            assertEquals(ISO_8859_2, t.getSourceEncoding());
         }
         {
             Template t = cfg.getTemplate(tUtf8Ftl, hu);
@@ -339,7 +339,7 @@ public class ConfigurationTest extends TestCase {
             assertEquals(tUtf8Ftl, t.getSourceName());
             assertEquals(hu, t.getLocale());
             assertNull(t.getCustomLookupCondition());
-            assertEquals(utf8, t.getSourceEncoding());
+            assertEquals(StandardCharsets.UTF_8, t.getSourceEncoding());
         }
 
         // 4 args:
@@ -356,7 +356,7 @@ public class ConfigurationTest extends TestCase {
             assertEquals(tHuFtl, t.getSourceName());
             assertEquals(hu, t.getLocale());
             assertEquals(custLookupCond, t.getCustomLookupCondition());
-            assertEquals(latin2, t.getSourceEncoding());
+            assertEquals(ISO_8859_2, t.getSourceEncoding());
             assertOutputEquals("1", t);
         }
         {
@@ -365,7 +365,7 @@ public class ConfigurationTest extends TestCase {
             assertEquals(tFtl, t.getSourceName());
             assertEquals(Locale.GERMAN, t.getLocale());
             assertEquals(custLookupCond, t.getCustomLookupCondition());
-            assertEquals(latin1, t.getSourceEncoding());
+            assertEquals(StandardCharsets.ISO_8859_1, t.getSourceEncoding());
             assertOutputEquals("1", t);
         }
     }
@@ -1336,24 +1336,22 @@ public class ConfigurationTest extends TestCase {
     public void testDefaultEncodingSetting() throws TemplateException, ConfigurationException {
         Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
 
-        String defaultFileEncoding = System.getProperty("file.encoding");
-        assertNotNull(defaultFileEncoding);
-
-        assertEquals(defaultFileEncoding, cfg.getSourceEncoding());
-        assertFalse(cfg.isDefaultEncodingExplicitlySet());
+        assertEquals(Charset.defaultCharset(), cfg.getSourceEncoding());
+        assertFalse(cfg.isSourceEncodingExplicitlySet());
 
-        String nonDefault = defaultFileEncoding.equalsIgnoreCase("UTF-8") ? "ISO-8859-1" : "UTF-8";
-        cfg.setEncoding(nonDefault);
-        assertTrue(cfg.isDefaultEncodingExplicitlySet());
+        Charset nonDefault = Charset.defaultCharset().equals(StandardCharsets.UTF_8) ? StandardCharsets.ISO_8859_1
+                : StandardCharsets.UTF_8;
+        cfg.setSourceEncoding(nonDefault);
+        assertTrue(cfg.isSourceEncodingExplicitlySet());
         assertEquals(nonDefault, cfg.getSourceEncoding());
 
-        cfg.unsetDefaultEncoding();
-        assertEquals(defaultFileEncoding, cfg.getSourceEncoding());
-        assertFalse(cfg.isDefaultEncodingExplicitlySet());
+        cfg.unsetSourceEncoding();
+        assertEquals(Charset.defaultCharset(), cfg.getSourceEncoding());
+        assertFalse(cfg.isSourceEncodingExplicitlySet());
 
         cfg.setSetting(Configuration.SOURCE_ENCODING_KEY, "JVM default");
-        assertEquals(defaultFileEncoding, cfg.getSourceEncoding());
-        assertTrue(cfg.isDefaultEncodingExplicitlySet());
+        assertEquals(Charset.defaultCharset(), cfg.getSourceEncoding());
+        assertTrue(cfg.isSourceEncodingExplicitlySet());
     }
 
     public void testTimeZoneSetting() throws TemplateException, ConfigurationException {
@@ -1453,10 +1451,10 @@ public class ConfigurationTest extends TestCase {
     public void testSetSettingSupportsBothNamingConventions() throws Exception {
         Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
         
-        cfg.setSetting(Configuration.SOURCE_ENCODING_KEY_CAMEL_CASE, "UTF-16LE");
-        assertEquals("UTF-16LE", cfg.getSourceEncoding());
-        cfg.setSetting(Configuration.SOURCE_ENCODING_KEY_SNAKE_CASE, "UTF-8");
-        assertEquals("UTF-8", cfg.getSourceEncoding());
+        cfg.setSetting(Configuration.SOURCE_ENCODING_KEY_CAMEL_CASE, StandardCharsets.UTF_16LE.name());
+        assertEquals(StandardCharsets.UTF_16LE, cfg.getSourceEncoding());
+        cfg.setSetting(Configuration.SOURCE_ENCODING_KEY_SNAKE_CASE, StandardCharsets.UTF_8.name());
+        assertEquals(StandardCharsets.UTF_8, cfg.getSourceEncoding());
         
         for (String nameCC : cfg.getSettingNames(true)) {
             for (String value : new String[] { "1", "default", "true" }) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/java/org/apache/freemarker/core/EncodingOverrideTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/core/EncodingOverrideTest.java b/src/test/java/org/apache/freemarker/core/EncodingOverrideTest.java
index d1b70eb..7648624 100644
--- a/src/test/java/org/apache/freemarker/core/EncodingOverrideTest.java
+++ b/src/test/java/org/apache/freemarker/core/EncodingOverrideTest.java
@@ -23,6 +23,8 @@ import static org.junit.Assert.*;
 
 import java.io.IOException;
 import java.io.StringWriter;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.util.Collections;
 
 import org.junit.Test;
@@ -30,36 +32,29 @@ import org.junit.Test;
 public class EncodingOverrideTest {
 
     @Test
-    public void testExactMarchingCharset() throws Exception {
-        Template t = createConfig("UTF-8").getTemplate("encodingOverride-UTF-8.ftl");
-        assertEquals("UTF-8", t.getSourceEncoding());
-        checkTempateOutput(t);
+    public void testMarchingCharset() throws Exception {
+        Template t = createConfig(StandardCharsets.UTF_8).getTemplate("encodingOverride-UTF-8.ftl");
+        assertEquals(StandardCharsets.UTF_8, t.getSourceEncoding());
+        checkTemplateOutput(t);
     }
 
     @Test
-    public void testCaseDiffCharset() throws Exception {
-        Template t = createConfig("utf-8").getTemplate("encodingOverride-UTF-8.ftl");
-        assertEquals("utf-8", t.getSourceEncoding());
-        checkTempateOutput(t);
+    public void testDifferentCharset() throws Exception {
+        Template t = createConfig(StandardCharsets.UTF_8).getTemplate("encodingOverride-ISO-8859-1.ftl");
+        assertEquals(StandardCharsets.ISO_8859_1, t.getSourceEncoding());
+        checkTemplateOutput(t);
     }
 
-    @Test
-    public void testReallyDiffCharset() throws Exception {
-        Template t = createConfig("utf-8").getTemplate("encodingOverride-ISO-8859-1.ftl");
-        assertEquals("ISO-8859-1", t.getSourceEncoding());
-        checkTempateOutput(t);
-    }
-
-    private void checkTempateOutput(Template t) throws TemplateException, IOException {
+    private void checkTemplateOutput(Template t) throws TemplateException, IOException {
         StringWriter out = new StringWriter(); 
         t.process(Collections.emptyMap(), out);
         assertEquals("B�ka", out.toString());
     }
     
-    private Configuration createConfig(String charset) {
+    private Configuration createConfig(Charset charset) {
        Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
        cfg.setClassForTemplateLoading(EncodingOverrideTest.class, "");
-       cfg.setEncoding(charset);
+       cfg.setSourceEncoding(charset);
        return cfg;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/java/org/apache/freemarker/core/ObjectBuilderSettingsTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/core/ObjectBuilderSettingsTest.java b/src/test/java/org/apache/freemarker/core/ObjectBuilderSettingsTest.java
index 10e4dfd..73e03f6 100644
--- a/src/test/java/org/apache/freemarker/core/ObjectBuilderSettingsTest.java
+++ b/src/test/java/org/apache/freemarker/core/ObjectBuilderSettingsTest.java
@@ -28,6 +28,9 @@ import java.io.Serializable;
 import java.io.Writer;
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.charset.UnsupportedCharsetException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -379,7 +382,7 @@ public class ObjectBuilderSettingsTest {
             assertEquals(DummyCacheStorage.class, cfg.getCacheStorage().getClass());
             assertEquals(DummyNewBuiltinClassResolver.class, cfg.getNewBuiltinClassResolver().getClass());
             assertEquals(DummyTemplateLoader.class, cfg.getTemplateLoader().getClass());
-            assertEquals("utf-8", cfg.getSourceEncoding());
+            assertEquals(StandardCharsets.UTF_8, cfg.getSourceEncoding());
         }
         
         {
@@ -401,7 +404,7 @@ public class ObjectBuilderSettingsTest {
                     ((DefaultObjectWrapper) cfg.getObjectWrapper()).getIncompatibleImprovements());
             assertEquals(500, ((MruCacheStorage) cfg.getCacheStorage()).getSoftSizeLimit());
             assertEquals(TemplateClassResolver.ALLOWS_NOTHING_RESOLVER, cfg.getNewBuiltinClassResolver());
-            assertEquals("utf-8", cfg.getSourceEncoding());
+            assertEquals(StandardCharsets.UTF_8, cfg.getSourceEncoding());
         }
 
         {
@@ -449,7 +452,27 @@ public class ObjectBuilderSettingsTest {
                     allOf(containsStringIgnoringCase("unrecognized"), containsString("foobar")));
         }
     }
-    
+
+    @Test
+    public void charsetTest() throws _ObjectBuilderSettingEvaluationException, ClassNotFoundException,
+            InstantiationException, IllegalAccessException {
+        for (String timeZoneId : new String[] { "uTf-8", "GMT", "UTC" }) {
+            TestBean8 result = (TestBean8) _ObjectBuilderSettingEvaluator.eval(
+                    "org.apache.freemarker.core.ObjectBuilderSettingsTest$TestBean8(charset=Charset('iso-8859-1'))",
+                    TestBean8.class, false, new _SettingEvaluationEnvironment());
+            assertEquals(StandardCharsets.ISO_8859_1, result.getCharset());
+        }
+
+        try {
+            _ObjectBuilderSettingEvaluator.eval(
+                    "org.apache.freemarker.core.ObjectBuilderSettingsTest$TestBean8(charset=Charset('noSuchCS'))",
+                    TestBean8.class, false, new _SettingEvaluationEnvironment());
+            fail();
+        } catch (_ObjectBuilderSettingEvaluationException e) {
+            assertThat(e.getCause(), instanceOf(UnsupportedCharsetException.class));
+        }
+    }
+
     @Test
     public void configureBeanTest() throws Exception {
         final TestBean7 bean = new TestBean7();
@@ -1263,6 +1286,7 @@ public class ObjectBuilderSettingsTest {
     
     public static class TestBean8 {
         private TimeZone timeZone;
+        private Charset charset;
         private Object anyObject;
         private List<?> list;
         
@@ -1273,7 +1297,15 @@ public class ObjectBuilderSettingsTest {
         public void setTimeZone(TimeZone timeZone) {
             this.timeZone = timeZone;
         }
-        
+
+        public Charset getCharset() {
+            return charset;
+        }
+
+        public void setCharset(Charset charset) {
+            this.charset = charset;
+        }
+
         public Object getAnyObject() {
             return anyObject;
         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/java/org/apache/freemarker/core/TemplateConfigurationTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/core/TemplateConfigurationTest.java b/src/test/java/org/apache/freemarker/core/TemplateConfigurationTest.java
index 3d851cf..7cbb0f6 100644
--- a/src/test/java/org/apache/freemarker/core/TemplateConfigurationTest.java
+++ b/src/test/java/org/apache/freemarker/core/TemplateConfigurationTest.java
@@ -30,6 +30,7 @@ import java.io.StringReader;
 import java.io.StringWriter;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -71,6 +72,8 @@ import com.google.common.collect.ImmutableMap;
 @SuppressWarnings("boxing")
 public class TemplateConfigurationTest {
 
+    private static final Charset ISO_8859_2 = Charset.forName("ISO-8859-2");
+
     private final class DummyArithmeticEngine extends ArithmeticEngine {
 
         @Override
@@ -133,33 +136,13 @@ public class TemplateConfigurationTest {
         NON_DEFAULT_TZ = tz;
     }
 
-    private static final Locale NON_DEFAULT_LOCALE;
-    static {
-        Locale defaultLocale = DEFAULT_CFG.getLocale();
-        Locale locale = Locale.GERMAN;
-        if (locale.equals(defaultLocale)) {
-            locale = Locale.US;
-            if (locale.equals(defaultLocale)) {
-                throw new AssertionError("Couldn't chose a non-default locale");
-            }
-        }
-        NON_DEFAULT_LOCALE = locale;
-    }
+    private static final Locale NON_DEFAULT_LOCALE =
+            DEFAULT_CFG.getLocale().equals(Locale.US) ? Locale.GERMAN : Locale.US;
 
-    private static final String NON_DEFAULT_ENCODING;
+    private static final Charset NON_DEFAULT_ENCODING =
+            DEFAULT_CFG.getSourceEncoding().equals(StandardCharsets.UTF_8) ? StandardCharsets.UTF_16LE
+                    : StandardCharsets.UTF_8;
 
-    static {
-        String defaultEncoding = DEFAULT_CFG.getSourceEncoding();
-        String encoding = "UTF-16";
-        if (encoding.equals(defaultEncoding)) {
-            encoding = "UTF-8";
-            if (encoding.equals(defaultEncoding)) {
-                throw new AssertionError("Couldn't chose a non-default locale");
-            }
-        }
-        NON_DEFAULT_ENCODING = encoding;
-    }
-    
     private static final Map<String, Object> SETTING_ASSIGNMENTS;
 
     static {
@@ -168,7 +151,7 @@ public class TemplateConfigurationTest {
         // "MutableProcessingConfiguration" settings:
         SETTING_ASSIGNMENTS.put("APIBuiltinEnabled", true);
         SETTING_ASSIGNMENTS.put("SQLDateAndTimeTimeZone", NON_DEFAULT_TZ);
-        SETTING_ASSIGNMENTS.put("URLEscapingCharset", "utf-16");
+        SETTING_ASSIGNMENTS.put("URLEscapingCharset", StandardCharsets.UTF_16);
         SETTING_ASSIGNMENTS.put("autoFlush", false);
         SETTING_ASSIGNMENTS.put("booleanFormat", "J,N");
         SETTING_ASSIGNMENTS.put("dateFormat", "yyyy-#DDD");
@@ -178,7 +161,7 @@ public class TemplateConfigurationTest {
         SETTING_ASSIGNMENTS.put("newBuiltinClassResolver", TemplateClassResolver.ALLOWS_NOTHING_RESOLVER);
         SETTING_ASSIGNMENTS.put("numberFormat", "0.0000");
         SETTING_ASSIGNMENTS.put("objectWrapper", new RestrictedObjectWrapper.Builder(ICI).build());
-        SETTING_ASSIGNMENTS.put("outputEncoding", "utf-16");
+        SETTING_ASSIGNMENTS.put("outputEncoding", StandardCharsets.UTF_16);
         SETTING_ASSIGNMENTS.put("showErrorTips", false);
         SETTING_ASSIGNMENTS.put("templateExceptionHandler", TemplateExceptionHandler.IGNORE_HANDLER);
         SETTING_ASSIGNMENTS.put("timeFormat", "@HH:mm");
@@ -710,10 +693,10 @@ public class TemplateConfigurationTest {
             // assertOutput here, as that hard-coded to create an FTL Template.
 
             TemplateConfiguration tc = new TemplateConfiguration();
-            tc.setSourceEncoding("ISO-8859-1");
+            tc.setSourceEncoding(StandardCharsets.ISO_8859_1);
 
             Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
-            cfg.setEncoding("utf-8");
+            cfg.setSourceEncoding(StandardCharsets.UTF_8);
             cfg.setTemplateConfigurations(new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher
                     ("latin1.ftl"), tc));
 
@@ -819,24 +802,24 @@ public class TemplateConfigurationTest {
         {
             TemplateConfiguration tc = new TemplateConfiguration();
             tc.setParentConfiguration(DEFAULT_CFG);
-            String outputEncoding = "ISO-8859-2";
+            Charset outputEncoding = ISO_8859_2;
             tc.setOutputEncoding(outputEncoding);
 
             String legacyNCFtl = "${r'.output_encoding!\"null\"'?eval}";
             String camelCaseNCFtl = "${r'.outputEncoding!\"null\"'?eval}";
 
             // Default is re-auto-detecting in ?eval:
-            assertOutputWithoutAndWithTC(tc, legacyNCFtl, "null", outputEncoding);
-            assertOutputWithoutAndWithTC(tc, camelCaseNCFtl, "null", outputEncoding);
+            assertOutputWithoutAndWithTC(tc, legacyNCFtl, "null", outputEncoding.name());
+            assertOutputWithoutAndWithTC(tc, camelCaseNCFtl, "null", outputEncoding.name());
             
             // Force camelCase:
             tc.setNamingConvention(Configuration.CAMEL_CASE_NAMING_CONVENTION);
             assertOutputWithoutAndWithTC(tc, legacyNCFtl, "null", null);
-            assertOutputWithoutAndWithTC(tc, camelCaseNCFtl, "null", outputEncoding);
+            assertOutputWithoutAndWithTC(tc, camelCaseNCFtl, "null", outputEncoding.name());
             
             // Force legacy:
             tc.setNamingConvention(Configuration.LEGACY_NAMING_CONVENTION);
-            assertOutputWithoutAndWithTC(tc, legacyNCFtl, "null", outputEncoding);
+            assertOutputWithoutAndWithTC(tc, legacyNCFtl, "null", outputEncoding.name());
             assertOutputWithoutAndWithTC(tc, camelCaseNCFtl, "null", null);
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/java/org/apache/freemarker/core/TemplateConfigurationWithDefaltTemplateResolverTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/core/TemplateConfigurationWithDefaltTemplateResolverTest.java b/src/test/java/org/apache/freemarker/core/TemplateConfigurationWithDefaltTemplateResolverTest.java
index af3ec9c..f26ce63 100644
--- a/src/test/java/org/apache/freemarker/core/TemplateConfigurationWithDefaltTemplateResolverTest.java
+++ b/src/test/java/org/apache/freemarker/core/TemplateConfigurationWithDefaltTemplateResolverTest.java
@@ -23,6 +23,8 @@ import static org.junit.Assert.*;
 import java.io.IOException;
 import java.io.StringWriter;
 import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.util.Locale;
 
 import org.apache.freemarker.core.templateresolver.ConditionalTemplateConfigurationFactory;
@@ -40,33 +42,35 @@ public class TemplateConfigurationWithDefaltTemplateResolverTest {
     private static final Object CUST_ATT_1 = new Object();
     private static final Object CUST_ATT_2 = new Object();
 
+    private static final Charset ISO_8859_2 = Charset.forName("ISO-8859-2");
+
     @Test
     public void testEncoding() throws Exception {
         Configuration cfg = createCommonEncodingTesterConfig();
         
         {
             Template t = cfg.getTemplate("utf8.ftl");
-            assertEquals("utf-8", t.getSourceEncoding());
+            assertEquals(StandardCharsets.UTF_8, t.getSourceEncoding());
             assertEquals(TEXT_WITH_ACCENTS, getTemplateOutput(t));
         }
         {
             Template t = cfg.getTemplate("utf16.ftl");
-            assertEquals("utf-16", t.getSourceEncoding());
+            assertEquals(StandardCharsets.UTF_16LE, t.getSourceEncoding());
             assertEquals(TEXT_WITH_ACCENTS, getTemplateOutput(t));
         }
         {
             Template t = cfg.getTemplate("default.ftl");
-            assertEquals("iso-8859-1", t.getSourceEncoding());
+            assertEquals(StandardCharsets.ISO_8859_1, t.getSourceEncoding());
             assertEquals(TEXT_WITH_ACCENTS, getTemplateOutput(t));
         }
         {
             Template t = cfg.getTemplate("utf8-latin2.ftl");
-            assertEquals("iso-8859-2", t.getSourceEncoding());
+            assertEquals(ISO_8859_2, t.getSourceEncoding());
             assertEquals(TEXT_WITH_ACCENTS, getTemplateOutput(t));
         }
         {
             Template t = cfg.getTemplate("default-latin2.ftl");
-            assertEquals("iso-8859-2", t.getSourceEncoding());
+            assertEquals(ISO_8859_2, t.getSourceEncoding());
             assertEquals(TEXT_WITH_ACCENTS, getTemplateOutput(t));
         }
     }
@@ -80,7 +84,7 @@ public class TemplateConfigurationWithDefaltTemplateResolverTest {
                         + "<#include 'utf16.ftl'>"
                         + "<#include 'default.ftl'>"
                         + "<#include 'utf8-latin2.ftl'>"
-                ).getBytes("iso-8859-1"));
+                ).getBytes(StandardCharsets.ISO_8859_1));
         assertEquals(
                 TEXT_WITH_ACCENTS + TEXT_WITH_ACCENTS + TEXT_WITH_ACCENTS + TEXT_WITH_ACCENTS,
                 getTemplateOutput(cfg.getTemplate("main.ftl")));
@@ -232,23 +236,23 @@ public class TemplateConfigurationWithDefaltTemplateResolverTest {
 
     private Configuration createCommonEncodingTesterConfig() throws UnsupportedEncodingException {
         Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
-        cfg.setEncoding("iso-8859-1");
+        cfg.setSourceEncoding(StandardCharsets.ISO_8859_1);
         cfg.setLocale(Locale.US);
         
         ByteArrayTemplateLoader tl = new ByteArrayTemplateLoader();
-        tl.putTemplate("utf8.ftl", TEXT_WITH_ACCENTS.getBytes("utf-8"));
-        tl.putTemplate("utf16.ftl", TEXT_WITH_ACCENTS.getBytes("utf-16"));
-        tl.putTemplate("default.ftl", TEXT_WITH_ACCENTS.getBytes("iso-8859-2"));
+        tl.putTemplate("utf8.ftl", TEXT_WITH_ACCENTS.getBytes(StandardCharsets.UTF_8));
+        tl.putTemplate("utf16.ftl", TEXT_WITH_ACCENTS.getBytes(StandardCharsets.UTF_16LE));
+        tl.putTemplate("default.ftl", TEXT_WITH_ACCENTS.getBytes(ISO_8859_2));
         tl.putTemplate("utf8-latin2.ftl",
-                ("<#ftl encoding='iso-8859-2'>" + TEXT_WITH_ACCENTS).getBytes("iso-8859-2"));
+                ("<#ftl encoding='iso-8859-2'>" + TEXT_WITH_ACCENTS).getBytes(ISO_8859_2));
         tl.putTemplate("default-latin2.ftl",
-                ("<#ftl encoding='iso-8859-2'>" + TEXT_WITH_ACCENTS).getBytes("iso-8859-2"));
+                ("<#ftl encoding='iso-8859-2'>" + TEXT_WITH_ACCENTS).getBytes(ISO_8859_2));
         cfg.setTemplateLoader(tl);
         
         TemplateConfiguration tcUtf8 = new TemplateConfiguration();
-        tcUtf8.setSourceEncoding("utf-8");
+        tcUtf8.setSourceEncoding(StandardCharsets.UTF_8);
         TemplateConfiguration tcUtf16 = new TemplateConfiguration();
-        tcUtf16.setSourceEncoding("utf-16");
+        tcUtf16.setSourceEncoding(StandardCharsets.UTF_16LE);
         cfg.setTemplateConfigurations(
                 new FirstMatchTemplateConfigurationFactory(
                         new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*utf8*"), tcUtf8),

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/java/org/apache/freemarker/core/TemplateConstructorsTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/core/TemplateConstructorsTest.java b/src/test/java/org/apache/freemarker/core/TemplateConstructorsTest.java
index aa011a7..dd73d79 100644
--- a/src/test/java/org/apache/freemarker/core/TemplateConstructorsTest.java
+++ b/src/test/java/org/apache/freemarker/core/TemplateConstructorsTest.java
@@ -25,81 +25,89 @@ import static org.junit.Assert.*;
 import java.io.IOException;
 import java.io.Reader;
 import java.io.StringReader;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 
 import org.junit.Test;
 public class TemplateConstructorsTest {
 
-    private static final String READER_CONTENT = "From a reader...";
-    private static final String READER_CONTENT_FORCE_UTF8 = "<#ftl encoding='utf-8'>From a reader...";
+    private static final String CONTENT = "From a reader...";
+    private static final String CONTENT_FORCE_UTF8 = "<#ftl encoding='utf-8'>From a reader...";
     
     @Test
     public void test() throws IOException {
         final Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
-        //cfg.setSourceEncoding("ISO-8859-1");
+        cfg.setSourceEncoding(StandardCharsets.ISO_8859_1);
         
         final String name = "foo/bar.ftl";
         final String sourceName = "foo/bar_de.ftl";
-        final String content = "From a String...";
-        final String encoding = "UTF-16LE";
+        final Charset sourceEncoding = StandardCharsets.UTF_16LE;
         {
             Template t = new Template(name, createReader(), cfg);
             assertEquals(name, t.getName());
             assertEquals(name, t.getSourceName());
-            assertEquals(READER_CONTENT, t.toString());
+            assertEquals(CONTENT, t.toString());
             assertNull(t.getSourceEncoding());
         }
         {
-            Template t = new Template(name, content, cfg);
+            Template t = new Template(name, CONTENT, cfg);
             assertEquals(name, t.getName());
             assertEquals(name, t.getSourceName());
-            assertEquals(content, t.toString());
+            assertEquals(CONTENT, t.toString());
             assertNull(t.getSourceEncoding());
         }
         {
-            Template t = new Template(name, createReader(), cfg, encoding);
+            Template t = new Template(name, CONTENT_FORCE_UTF8, cfg);
             assertEquals(name, t.getName());
             assertEquals(name, t.getSourceName());
-            assertEquals(READER_CONTENT, t.toString());
-            assertEquals("UTF-16LE", t.getSourceEncoding());
+            // assertEquals(CONTENT_FORCE_UTF8, t.toString()); // FIXME the #ftl header is missing from the dump, why?
+            assertNull(t.getSourceEncoding()); // Because it was created from a String
+        }
+        {
+            Template t = new Template(name, createReader(), cfg, sourceEncoding);
+            assertEquals(name, t.getName());
+            assertEquals(name, t.getSourceName());
+            assertEquals(CONTENT, t.toString());
+            assertEquals(StandardCharsets.UTF_16LE, t.getSourceEncoding());
         }
         {
             Template t = new Template(name, sourceName, createReader(), cfg);
             assertEquals(name, t.getName());
             assertEquals(sourceName, t.getSourceName());
-            assertEquals(READER_CONTENT, t.toString());
+            assertEquals(CONTENT, t.toString());
             assertNull(t.getSourceEncoding());
         }
         {
-            Template t = new Template(name, sourceName, createReader(), cfg, encoding);
+            Template t = new Template(name, sourceName, createReader(), cfg, sourceEncoding);
             assertEquals(name, t.getName());
             assertEquals(sourceName, t.getSourceName());
-            assertEquals(READER_CONTENT, t.toString());
-            assertEquals("UTF-16LE", t.getSourceEncoding());
+            assertEquals(CONTENT, t.toString());
+            assertEquals(StandardCharsets.UTF_16LE, t.getSourceEncoding());
         }
         {
-            Template t = Template.createPlainTextTemplate(name, content, cfg);
+            Template t = Template.createPlainTextTemplate(name, CONTENT, cfg);
             assertEquals(name, t.getName());
             assertEquals(name, t.getSourceName());
-            assertEquals(content, t.toString());
+            assertEquals(CONTENT, t.toString());
             assertNull(t.getSourceEncoding());
         }
         {
             try {
-                new Template(name, sourceName, createReaderForceUTF8(), cfg, encoding);
+                new Template(name, sourceName, createReaderForceUTF8(), cfg, sourceEncoding);
                 fail();
             } catch (WrongTemplateCharsetException e) {
-                assertThat(e.getMessage(), containsString("utf-8"));
-                assertThat(e.getMessage(), containsString(encoding));
+                assertThat(e.getMessage(), containsString(StandardCharsets.UTF_8.name()));
+                assertThat(e.getMessage(), containsString(sourceEncoding.name()));
             }
         }
     }
     
     private Reader createReader() {
-        return new StringReader(READER_CONTENT);
+        return new StringReader(CONTENT);
     }
 
     private Reader createReaderForceUTF8() {
-        return new StringReader(READER_CONTENT_FORCE_UTF8);
+        return new StringReader(CONTENT_FORCE_UTF8);
     }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/java/org/apache/freemarker/core/TemplateGetEncodingTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/core/TemplateGetEncodingTest.java b/src/test/java/org/apache/freemarker/core/TemplateGetEncodingTest.java
index 685e6ba..c049cde 100644
--- a/src/test/java/org/apache/freemarker/core/TemplateGetEncodingTest.java
+++ b/src/test/java/org/apache/freemarker/core/TemplateGetEncodingTest.java
@@ -21,6 +21,7 @@ package org.apache.freemarker.core;
 import static org.junit.Assert.*;
 
 import java.io.IOException;
+import java.nio.charset.Charset;
 
 import org.apache.freemarker.core.templateresolver.ConditionalTemplateConfigurationFactory;
 import org.apache.freemarker.core.templateresolver.FileNameGlobMatcher;
@@ -30,11 +31,14 @@ import org.junit.Test;
 
 public class TemplateGetEncodingTest {
 
+    private static final Charset ISO_8859_2 = Charset.forName("ISO-8859-2");
+
     @Test
     public void test() throws IOException {
+
         Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
         {
-            cfg.setEncoding("ISO-8859-2");
+            cfg.setSourceEncoding(ISO_8859_2);
             MonitoredTemplateLoader tl = new MonitoredTemplateLoader();
             tl.putBinaryTemplate("bin", "test");
             tl.putBinaryTemplate("bin-static", "<#test>");
@@ -48,8 +52,8 @@ public class TemplateGetEncodingTest {
             cfg.setCacheStorage(new StrongCacheStorage());
         }
 
-        assertEquals("ISO-8859-2", cfg.getTemplate("bin").getSourceEncoding());
-        assertEquals("ISO-8859-2", cfg.getTemplate("bin-static").getSourceEncoding());
+        assertEquals(ISO_8859_2, cfg.getTemplate("bin").getSourceEncoding());
+        assertEquals(ISO_8859_2, cfg.getTemplate("bin-static").getSourceEncoding());
         assertNull(cfg.getTemplate("text").getSourceEncoding());
         assertNull(cfg.getTemplate("text-static").getSourceEncoding());
         assertNull(new Template(null, "test", cfg).getSourceEncoding());

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/java/org/apache/freemarker/core/templateresolver/DefaultTemplateResolverTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/core/templateresolver/DefaultTemplateResolverTest.java b/src/test/java/org/apache/freemarker/core/templateresolver/DefaultTemplateResolverTest.java
index 3605f4b..bfbcd5d 100644
--- a/src/test/java/org/apache/freemarker/core/templateresolver/DefaultTemplateResolverTest.java
+++ b/src/test/java/org/apache/freemarker/core/templateresolver/DefaultTemplateResolverTest.java
@@ -273,7 +273,7 @@ public class DefaultTemplateResolverTest {
     public void testWrongEncodingReload() throws IOException {
         Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
         cfg.setLocale(Locale.US);
-        cfg.setEncoding("utf-8");
+        cfg.setSourceEncoding(StandardCharsets.UTF_8);
         
         MonitoredTemplateLoader tl = new MonitoredTemplateLoader();
         tl.putBinaryTemplate("utf-8_en.ftl", "<#ftl encoding='utf-8'>B�ka");
@@ -286,7 +286,7 @@ public class DefaultTemplateResolverTest {
             Template t = cfg.getTemplate("utf-8.ftl");
             assertEquals("utf-8.ftl", t.getName());
             assertEquals("utf-8_en.ftl", t.getSourceName());
-            assertEquals("utf-8", t.getSourceEncoding());
+            assertEquals(StandardCharsets.UTF_8, t.getSourceEncoding());
             assertEquals("B�ka", t.toString());
             
             assertEquals(
@@ -304,7 +304,7 @@ public class DefaultTemplateResolverTest {
             Template t = cfg.getTemplate("iso-8859-1.ftl");
             assertEquals("iso-8859-1.ftl", t.getName());
             assertEquals("iso-8859-1_en_US.ftl", t.getSourceName());
-            assertEquals("ISO-8859-1", t.getSourceEncoding());
+            assertEquals(StandardCharsets.ISO_8859_1, t.getSourceEncoding());
             assertEquals("B�ka", t.toString());
             
             assertEquals(
@@ -320,7 +320,7 @@ public class DefaultTemplateResolverTest {
     public void testNoWrongEncodingForTemplateLoader2WithReader() throws IOException {
         Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
         cfg.setLocale(Locale.US);
-        cfg.setEncoding("utf-8");
+        cfg.setSourceEncoding(StandardCharsets.UTF_8);
         
         MonitoredTemplateLoader tl = new MonitoredTemplateLoader();
         tl.putTextTemplate("foo_en.ftl", "<#ftl encoding='utf-8'>\u0151");

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/java/org/apache/freemarker/manualtest/GettingStartedExample.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/manualtest/GettingStartedExample.java b/src/test/java/org/apache/freemarker/manualtest/GettingStartedExample.java
index f03e417..e6a244a 100644
--- a/src/test/java/org/apache/freemarker/manualtest/GettingStartedExample.java
+++ b/src/test/java/org/apache/freemarker/manualtest/GettingStartedExample.java
@@ -20,6 +20,7 @@ package org.apache.freemarker.manualtest;
 
 import java.io.OutputStreamWriter;
 import java.io.Writer;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -38,7 +39,7 @@ public class GettingStartedExample {
         /* Create and adjust the configuration singleton */
         Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
         cfg.setClassForTemplateLoading(GettingStartedExample.class, "");
-        cfg.setEncoding("UTF-8");
+        cfg.setSourceEncoding(StandardCharsets.UTF_8);
         cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
         cfg.setLogTemplateExceptions(false);
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/java/org/apache/freemarker/manualtest/TemplateConfigurationExamples.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/manualtest/TemplateConfigurationExamples.java b/src/test/java/org/apache/freemarker/manualtest/TemplateConfigurationExamples.java
index 49efff1..3896a2e 100644
--- a/src/test/java/org/apache/freemarker/manualtest/TemplateConfigurationExamples.java
+++ b/src/test/java/org/apache/freemarker/manualtest/TemplateConfigurationExamples.java
@@ -20,6 +20,7 @@ package org.apache.freemarker.manualtest;
 
 import static org.junit.Assert.*;
 
+import java.nio.charset.StandardCharsets;
 import java.util.Date;
 
 import org.apache.freemarker.core.Configuration;
@@ -48,7 +49,7 @@ public class TemplateConfigurationExamples extends ExamplesTest {
         addTemplate("t.xml", "");
         
         TemplateConfiguration tcUTF8XML = new TemplateConfiguration();
-        tcUTF8XML.setSourceEncoding("utf-8");
+        tcUTF8XML.setSourceEncoding(StandardCharsets.UTF_8);
         tcUTF8XML.setOutputFormat(XMLOutputFormat.INSTANCE);
 
         {
@@ -56,7 +57,7 @@ public class TemplateConfigurationExamples extends ExamplesTest {
                     new FileExtensionMatcher("xml"), tcUTF8XML));
             
             Template t = cfg.getTemplate("t.xml");
-            assertEquals("utf-8", t.getSourceEncoding());
+            assertEquals(StandardCharsets.UTF_8, t.getSourceEncoding());
             assertEquals(XMLOutputFormat.INSTANCE, t.getOutputFormat());
         }
 
@@ -65,7 +66,7 @@ public class TemplateConfigurationExamples extends ExamplesTest {
             cfg.setSettings(loadPropertiesFile("TemplateConfigurationExamples1.properties"));
             
             Template t = cfg.getTemplate("t.xml");
-            assertEquals("utf-8", t.getSourceEncoding());
+            assertEquals(StandardCharsets.UTF_8, t.getSourceEncoding());
             assertEquals(XMLOutputFormat.INSTANCE, t.getOutputFormat());
         }
     }
@@ -115,7 +116,7 @@ public class TemplateConfigurationExamples extends ExamplesTest {
     @Test
     public void example3() throws Exception {
         Configuration cfg = getConfiguration();
-        cfg.setEncoding("ISO-8859-1");
+        cfg.setSourceEncoding(StandardCharsets.ISO_8859_1);
         cfg.setSharedVariable("ts", new Date(1440431606011L));
         
         addTemplate("t.stats.html", "${ts?datetime} ${ts?date} ${ts?time}");
@@ -131,7 +132,7 @@ public class TemplateConfigurationExamples extends ExamplesTest {
         tcStats.setTimeZone(_DateUtil.UTC);
 
         TemplateConfiguration tcMail = new TemplateConfiguration();
-        tcMail.setSourceEncoding("utf-8");
+        tcMail.setSourceEncoding(StandardCharsets.UTF_8);
         
         TemplateConfiguration tcHTML = new TemplateConfiguration();
         tcHTML.setOutputFormat(HTMLOutputFormat.INSTANCE);
@@ -161,12 +162,12 @@ public class TemplateConfigurationExamples extends ExamplesTest {
         );
         
         assertEquals(HTMLOutputFormat.INSTANCE, cfg.getTemplate("t.html").getOutputFormat());
-        assertEquals("ISO-8859-1", cfg.getTemplate("t.html").getSourceEncoding());
+        assertEquals(StandardCharsets.ISO_8859_1, cfg.getTemplate("t.html").getSourceEncoding());
         assertEquals(HTMLOutputFormat.INSTANCE, cfg.getTemplate("t.htm").getOutputFormat());
         assertEquals(XMLOutputFormat.INSTANCE, cfg.getTemplate("t.xml").getOutputFormat());
         assertEquals(HTMLOutputFormat.INSTANCE, cfg.getTemplate("t.stats.html").getOutputFormat());
         assertOutputForNamed("t.stats.html", "2015-08-24T15:53:26.011Z 2015-08-24 15:53:26.011Z");
-        assertEquals("utf-8", cfg.getTemplate("mail/t.html").getSourceEncoding());
+        assertEquals(StandardCharsets.UTF_8, cfg.getTemplate("mail/t.html").getSourceEncoding());
         
         // From properties:
         
@@ -174,12 +175,12 @@ public class TemplateConfigurationExamples extends ExamplesTest {
         cfg.setSettings(loadPropertiesFile("TemplateConfigurationExamples3.properties"));
         
         assertEquals(HTMLOutputFormat.INSTANCE, cfg.getTemplate("t.html").getOutputFormat());
-        assertEquals("ISO-8859-1", cfg.getTemplate("t.html").getSourceEncoding());
+        assertEquals(StandardCharsets.ISO_8859_1, cfg.getTemplate("t.html").getSourceEncoding());
         assertEquals(HTMLOutputFormat.INSTANCE, cfg.getTemplate("t.htm").getOutputFormat());
         assertEquals(XMLOutputFormat.INSTANCE, cfg.getTemplate("t.xml").getOutputFormat());
         assertEquals(HTMLOutputFormat.INSTANCE, cfg.getTemplate("t.stats.html").getOutputFormat());
         assertOutputForNamed("t.stats.html", "2015-08-24T15:53:26.011Z 2015-08-24 15:53:26.011Z");
-        assertEquals("utf-8", cfg.getTemplate("mail/t.html").getSourceEncoding());
+        assertEquals(StandardCharsets.UTF_8, cfg.getTemplate("mail/t.html").getSourceEncoding());
     }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/java/org/apache/freemarker/servlet/FreemarkerServletTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/servlet/FreemarkerServletTest.java b/src/test/java/org/apache/freemarker/servlet/FreemarkerServletTest.java
index daa44a9..d638025 100644
--- a/src/test/java/org/apache/freemarker/servlet/FreemarkerServletTest.java
+++ b/src/test/java/org/apache/freemarker/servlet/FreemarkerServletTest.java
@@ -23,6 +23,7 @@ import static org.hamcrest.Matchers.*;
 import static org.junit.Assert.*;
 
 import java.io.IOException;
+import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import java.nio.charset.UnsupportedCharsetException;
 import java.util.Locale;
@@ -67,11 +68,13 @@ public class FreemarkerServletTest {
     private static final String STD_OUTPUT_FORMAT_RTF_FTL = "stdOutputFormatRTF.ftl";
 
     private static final Locale DEFAULT_LOCALE = Locale.US;
-    private static final String CFG_DEFAULT_ENCODING = "US-ASCII";
+    private static final Charset CFG_DEFAULT_ENCODING = StandardCharsets.US_ASCII;
     /** According to the Servlet Specification */
-    private static final String SERVLET_RESPONSE_DEFAULT_CHARSET = "ISO-8859-1";
+    private static final Charset SERVLET_RESPONSE_DEFAULT_CHARSET = StandardCharsets.ISO_8859_1;
     private static final String DEFAULT_CONTENT_TYPE = "text/html";
 
+    private static final Charset ISO_8859_2 = Charset.forName("ISO-8859-2");
+
     private MockServletContext servletContext;
 
     @Before
@@ -242,36 +245,36 @@ public class FreemarkerServletTest {
                     FOO_FTL);
             // Legacy mode follows the source encoding of the template:
             assertOutputEncodingEquals(
-                    "UTF-8", // <- expected response.characterEncoding
+                    StandardCharsets.UTF_8, // <- expected response.characterEncoding
                     null, // <- expected env.outputEncoding
                     initParamValue, // <- init-param
                     FOO_SRC_UTF8_FTL);
             // Legacy mode doesn't deal with outputEncoding, but it's inherited by the Environment from the Template:
             assertOutputEncodingEquals(
                     CFG_DEFAULT_ENCODING, // <- expected response.characterEncoding
-                    "UTF-8", // <- expected env.outputEncoding
+                    StandardCharsets.UTF_8, // <- expected env.outputEncoding
                     initParamValue, // <- init-param
                     FOO_OUT_UTF8_FTL);
             // Charset in content type is the strongest:
             assertOutputEncodingEquals(
-                    "ISO-8859-2", // <- expected response.characterEncoding
+                    ISO_8859_2, // <- expected response.characterEncoding
                     null, // <- expected env.outputEncoding
                     initParamValue, // <- init-param
                     "text/html; charset=ISO-8859-2", // ContentType init-param
                     FOO_FTL);
             assertOutputEncodingEquals(
-                    "ISO-8859-2", // <- expected response.characterEncoding
+                    ISO_8859_2, // <- expected response.characterEncoding
                     null, // <- expected env.outputEncoding
                     initParamValue, // <- init-param
                     "text/html; charset=ISO-8859-2", // ContentType init-param
                     FOO_SRC_UTF8_FTL);
             assertOutputEncodingEquals(
-                    "UTF-8", // <- expected response.characterEncoding
+                    StandardCharsets.UTF_8, // <- expected response.characterEncoding
                     null, // <- expected env.outputEncoding
                     initParamValue, // <- init-param
                     CONTENT_TYPE_ATTR_WITH_CHARSET_FTL);
             assertOutputEncodingEquals(
-                    "UTF-8", // <- expected response.characterEncoding
+                    StandardCharsets.UTF_8, // <- expected response.characterEncoding
                     null, // <- expected env.outputEncoding
                     initParamValue, // <- init-param
                     "text/html; charset=ISO-8859-2", // ContentType init-param
@@ -286,14 +289,14 @@ public class FreemarkerServletTest {
                 FOO_FTL);
         // Non-legacy mode considers the template-specific outputEncoding:
         assertOutputEncodingEquals(
-                "UTF-8", // <- expected response.characterEncoding
-                "UTF-8", // <- expected env.outputEncoding
+                StandardCharsets.UTF_8, // <- expected response.characterEncoding
+                StandardCharsets.UTF_8, // <- expected env.outputEncoding
                 FreemarkerServlet.INIT_PARAM_VALUE_FROM_TEMPLATE, // <- init-param
                 FOO_OUT_UTF8_FTL);
         // Non-legacy mode uses the template source encoding as a fallback for outputEncoding:
         assertOutputEncodingEquals(
-                "UTF-8", // <- expected response.characterEncoding
-                "UTF-8", // <- expected env.outputEncoding
+                StandardCharsets.UTF_8, // <- expected response.characterEncoding
+                StandardCharsets.UTF_8, // <- expected env.outputEncoding
                 FreemarkerServlet.INIT_PARAM_VALUE_FROM_TEMPLATE, // <- init-param
                 FOO_SRC_UTF8_FTL);
         // Not allowed to specify the charset in the contentType init-param: 
@@ -310,8 +313,8 @@ public class FreemarkerServletTest {
         }
         // But the legacy content_type template attribute can still set the output charset:
         assertOutputEncodingEquals(
-                "UTF-8", // <- expected response.characterEncoding
-                "UTF-8", // <- expected env.outputEncoding
+                StandardCharsets.UTF_8, // <- expected response.characterEncoding
+                StandardCharsets.UTF_8, // <- expected env.outputEncoding
                 FreemarkerServlet.INIT_PARAM_VALUE_FROM_TEMPLATE, // <- init-param
                 CONTENT_TYPE_ATTR_WITH_CHARSET_FTL);
         
@@ -352,18 +355,18 @@ public class FreemarkerServletTest {
         
         // Forced mode:
         assertOutputEncodingEquals(
-                "UTF-16LE", // <- expected response.characterEncoding
-                "UTF-16LE", // <- expected env.outputEncoding
+                StandardCharsets.UTF_16LE, // <- expected response.characterEncoding
+                StandardCharsets.UTF_16LE, // <- expected env.outputEncoding
                 FreemarkerServlet.INIT_PARAM_VALUE_FORCE_PREFIX + "UTF-16LE", // <- init-param
                 FOO_FTL);
         assertOutputEncodingEquals(
-                "UTF-16LE", // <- expected response.characterEncoding
-                "UTF-16LE", // <- expected env.outputEncoding
+                StandardCharsets.UTF_16LE, // <- expected response.characterEncoding
+                StandardCharsets.UTF_16LE, // <- expected env.outputEncoding
                 FreemarkerServlet.INIT_PARAM_VALUE_FORCE_PREFIX + "UTF-16LE", // <- init-param
                 FOO_SRC_UTF8_FTL);
         assertOutputEncodingEquals(
-                "UTF-16LE", // <- expected response.characterEncoding
-                "UTF-16LE", // <- expected env.outputEncoding
+                StandardCharsets.UTF_16LE, // <- expected response.characterEncoding
+                StandardCharsets.UTF_16LE, // <- expected env.outputEncoding
                 FreemarkerServlet.INIT_PARAM_VALUE_FORCE_PREFIX + "UTF-16LE", // <- init-param
                 FOO_OUT_UTF8_FTL);
         try {
@@ -379,8 +382,8 @@ public class FreemarkerServletTest {
         // Not allowed to specify the charset in the contentType init-param: 
         try {
             assertOutputEncodingEquals(
-                    "UTF-16LE", // <- expected response.characterEncoding
-                    "UTF-16LE", // <- expected env.outputEncoding
+                    StandardCharsets.UTF_16LE, // <- expected response.characterEncoding
+                    StandardCharsets.UTF_16LE, // <- expected env.outputEncoding
                     FreemarkerServlet.INIT_PARAM_VALUE_FORCE_PREFIX + "UTF-16LE", // <- init-param
                     "text/html; charset=ISO-8859-2", // ContentType init-param
                     FOO_FTL);
@@ -390,14 +393,14 @@ public class FreemarkerServletTest {
         }
         // The legacy content_type template attribute can still specify an output charset, though it will be overridden:
         assertOutputEncodingEquals(
-                "UTF-16LE", // <- expected response.characterEncoding
-                "UTF-16LE", // <- expected env.outputEncoding
+                StandardCharsets.UTF_16LE, // <- expected response.characterEncoding
+                StandardCharsets.UTF_16LE, // <- expected env.outputEncoding
                 FreemarkerServlet.INIT_PARAM_VALUE_FORCE_PREFIX + "UTF-16LE", // <- init-param
                 CONTENT_TYPE_ATTR_WITH_CHARSET_FTL);
     }
 
     private void assertResponseContentTypeEquals(
-            String exptectContentType,
+            String expectedContentType,
             String ctInitParam, String overrideCTInitParam,
             String templateName, String responseCT)
                     throws ServletException, IOException {
@@ -412,7 +415,7 @@ public class FreemarkerServletTest {
         }
 
         MockServletConfig servletConfig = new MockServletConfig(servletContext);
-        servletConfig.addInitParameter(Configuration.SOURCE_ENCODING_KEY, "UTF-8");
+        servletConfig.addInitParameter(Configuration.SOURCE_ENCODING_KEY, "UtF-8");
         if (ctInitParam != null) {
             servletConfig.addInitParameter(INIT_PARAM_CONTENT_TYPE, ctInitParam);
         }
@@ -427,14 +430,14 @@ public class FreemarkerServletTest {
             freemarkerServlet.doGet(request, response);
 
             assertEquals(HttpServletResponse.SC_OK, response.getStatus());
-            assertEquals(exptectContentType, response.getContentType());
+            assertEquals(expectedContentType, response.getContentType());
         } finally {
             freemarkerServlet.destroy();
         }
     }
 
     private void assertTemplateLocaleEquals(
-            Locale exptectLocale,
+            Locale expectedLocale,
             Locale requestLocale,
             String overrideResponseLocaleInitParam,
             String templateName)
@@ -455,7 +458,7 @@ public class FreemarkerServletTest {
             freemarkerServlet.doGet(request, response);
 
             assertEquals(HttpServletResponse.SC_OK, response.getStatus());
-            assertEquals(exptectLocale, freemarkerServlet.lastLocale);
+            assertEquals(expectedLocale, freemarkerServlet.lastLocale);
             assertEquals(freemarkerServlet.lastLocale, freemarkerServlet.lastMainTemplate.getLocale());
         } finally {
             freemarkerServlet.destroy();
@@ -463,19 +466,19 @@ public class FreemarkerServletTest {
     }
 
     private void assertOutputEncodingEquals(
-            String exptectRespCharacterEncoding,
-            String exptectEnvOutputEncoding,
+            Charset expectedRespCharacterEncoding,
+            Charset expectedEnvOutputEncoding,
             String responseCharacterEncodingInitParam,
             String templateName) throws ServletException, IOException {
         assertOutputEncodingEquals(
-                exptectRespCharacterEncoding, exptectEnvOutputEncoding,
+                expectedRespCharacterEncoding, expectedEnvOutputEncoding,
                 responseCharacterEncodingInitParam, null,
                 templateName);
     }
     
     private void assertOutputEncodingEquals(
-            String exptectRespCharacterEncoding,
-            String exptectEnvOutputEncoding,
+            Charset expectedRespCharacterEncoding,
+            Charset expectedEnvOutputEncoding,
             String responseCharacterEncodingInitParam,
             String contentTypeInitParam,
             String templateName)
@@ -500,8 +503,9 @@ public class FreemarkerServletTest {
             freemarkerServlet.doGet(request, response);
 
             assertEquals(HttpServletResponse.SC_OK, response.getStatus());
-            assertEquals(exptectEnvOutputEncoding, freemarkerServlet.lastOutputEncoding);
-            assertEquals(exptectRespCharacterEncoding, response.getCharacterEncoding());
+            assertEquals(expectedEnvOutputEncoding, freemarkerServlet.lastOutputEncoding);
+            assertEquals(expectedRespCharacterEncoding,
+                    response.getCharacterEncoding() != null ? Charset.forName (response.getCharacterEncoding()) : null);
         } finally {
             freemarkerServlet.destroy();
         }
@@ -530,7 +534,7 @@ public class FreemarkerServletTest {
 
         private Template lastMainTemplate;
         private Locale lastLocale;
-        private String lastOutputEncoding;
+        private Charset lastOutputEncoding;
 
         @Override
         protected Configuration createConfiguration() {
@@ -540,14 +544,14 @@ public class FreemarkerServletTest {
 
             // Set a test runner environment independent default locale:
             cfg.setLocale(DEFAULT_LOCALE);
-            cfg.setEncoding(CFG_DEFAULT_ENCODING);
+            cfg.setSourceEncoding(CFG_DEFAULT_ENCODING);
 
             {
                 TemplateConfiguration outUtf8TC = new TemplateConfiguration();
-                outUtf8TC.setOutputEncoding("UTF-8");
+                outUtf8TC.setOutputEncoding(StandardCharsets.UTF_8);
                 
                 TemplateConfiguration srcUtf8TC = new TemplateConfiguration();
-                srcUtf8TC.setSourceEncoding("UTF-8");
+                srcUtf8TC.setSourceEncoding(StandardCharsets.UTF_8);
                 
                 cfg.setTemplateConfigurations(
                         new FirstMatchTemplateConfigurationFactory(

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/java/org/apache/freemarker/test/ResourcesExtractor.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/test/ResourcesExtractor.java b/src/test/java/org/apache/freemarker/test/ResourcesExtractor.java
index e36d845..ce9598e 100644
--- a/src/test/java/org/apache/freemarker/test/ResourcesExtractor.java
+++ b/src/test/java/org/apache/freemarker/test/ResourcesExtractor.java
@@ -25,6 +25,7 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
 import java.util.jar.JarOutputStream;
 import java.util.zip.ZipEntry;
 
@@ -99,7 +100,7 @@ public final class ResourcesExtractor {
             deleteDstRootDir = !dstRootDir.exists();
         }
         try {
-            BufferedReader contR = new BufferedReader(new InputStreamReader(contIn, "UTF-8"));
+            BufferedReader contR = new BufferedReader(new InputStreamReader(contIn, StandardCharsets.UTF_8));
             try {
                 String contLine;
                 while ((contLine = contR.readLine()) != null) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/java/org/apache/freemarker/test/TemplateTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/test/TemplateTest.java b/src/test/java/org/apache/freemarker/test/TemplateTest.java
index 31ad3e0..d42984f 100644
--- a/src/test/java/org/apache/freemarker/test/TemplateTest.java
+++ b/src/test/java/org/apache/freemarker/test/TemplateTest.java
@@ -77,8 +77,8 @@ public abstract class TemplateTest {
         if (!configuration.isLocaleExplicitlySet()) {
             configuration.setLocale(Locale.US);
         }
-        if (!configuration.isDefaultEncodingExplicitlySet()) {
-            configuration.setEncoding(StandardCharsets.UTF_8.name());
+        if (!configuration.isSourceEncodingExplicitlySet()) {
+            configuration.setSourceEncoding(StandardCharsets.UTF_8);
         }
         if (!configuration.isTimeZoneExplicitlySet()) {
             configuration.setTimeZone(TimeZone.getTimeZone("GMT+1"));
@@ -115,7 +115,7 @@ public abstract class TemplateTest {
                 throw new IOException("Reference output resource not found: " + getClass() + ", " + resName);
             }
             try {
-                expectedOut = TestUtil.removeTxtCopyrightComment(IOUtils.toString(in, "utf-8"));
+                expectedOut = TestUtil.removeTxtCopyrightComment(IOUtils.toString(in, StandardCharsets.UTF_8.name()));
             } finally {
                 in.close();
             }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/java/org/apache/freemarker/test/servlet/Model2TesterServlet.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/test/servlet/Model2TesterServlet.java b/src/test/java/org/apache/freemarker/test/servlet/Model2TesterServlet.java
index e6a8eab..9a39705 100644
--- a/src/test/java/org/apache/freemarker/test/servlet/Model2TesterServlet.java
+++ b/src/test/java/org/apache/freemarker/test/servlet/Model2TesterServlet.java
@@ -20,6 +20,7 @@
 package org.apache.freemarker.test.servlet;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 
 import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletException;
@@ -52,7 +53,7 @@ public class Model2TesterServlet extends HttpServlet {
 
     private static final long serialVersionUID = 1L;
 
-    private static final String CHARSET = "UTF-8";
+    private static final String CHARSET = StandardCharsets.UTF_8.name();
 
     @Override
     protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException,

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/java/org/apache/freemarker/test/servlet/WebAppTestCase.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/test/servlet/WebAppTestCase.java b/src/test/java/org/apache/freemarker/test/servlet/WebAppTestCase.java
index 1580932..5d68588 100644
--- a/src/test/java/org/apache/freemarker/test/servlet/WebAppTestCase.java
+++ b/src/test/java/org/apache/freemarker/test/servlet/WebAppTestCase.java
@@ -27,6 +27,7 @@ import java.io.InputStream;
 import java.net.HttpURLConnection;
 import java.net.URI;
 import java.net.URL;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -125,7 +126,7 @@ public class WebAppTestCase {
             if (responseCode == 200) {
                 InputStream in = httpCon.getInputStream();
                 try {
-                    content = IOUtils.toString(in, "UTF-8");
+                    content = IOUtils.toString(in, StandardCharsets.UTF_8.name());
                 } finally {
                     in.close();
                 }
@@ -191,7 +192,9 @@ public class WebAppTestCase {
                 throw new IOException("Test resource not found: " + expectedResource);
             }
             try {
-                expected = TestUtil.removeTxtCopyrightComment(normalizeWS(IOUtils.toString(in, "utf-8"), compressWS));
+                expected = TestUtil.removeTxtCopyrightComment(normalizeWS(
+                        IOUtils.toString(in, StandardCharsets.UTF_8.name()),
+                        compressWS));
             } finally {
                 in.close();
             }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/java/org/apache/freemarker/test/templatesuite/TemplateTestCase.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/test/templatesuite/TemplateTestCase.java b/src/test/java/org/apache/freemarker/test/templatesuite/TemplateTestCase.java
index fccef43..3e92a10 100644
--- a/src/test/java/org/apache/freemarker/test/templatesuite/TemplateTestCase.java
+++ b/src/test/java/org/apache/freemarker/test/templatesuite/TemplateTestCase.java
@@ -25,6 +25,8 @@ import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
@@ -146,8 +148,8 @@ public class TemplateTestCase extends FileTestCase {
             if (!st.hasMoreTokens()) fail("Expecting alias after 'as' in autoimport");
             String alias = st.nextToken();
             conf.addAutoImport(alias, libname);
-        } else if ("input_encoding".equals(param)) {
-            conf.setEncoding(value);
+        } else if ("source_encoding".equals(param)) {
+            conf.setSourceEncoding(Charset.forName(value));
         // INCOMPATIBLE_IMPROVEMENTS is a list here, and was already set in the constructor.
         } else if (!Configuration.INCOMPATIBLE_IMPROVEMENTS_KEY.equals(param)) {
             try {
@@ -425,8 +427,8 @@ public class TemplateTestCase extends FileTestCase {
     }
 
     @Override
-    protected String getDefaultCharset() {
-        return conf.getOutputEncoding() != null ? conf.getOutputEncoding() : "UTF-8";
+    protected Charset getFileCharset() {
+        return conf.getOutputEncoding() != null ? conf.getOutputEncoding() : StandardCharsets.UTF_8;
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/java/org/apache/freemarker/test/util/FileTestCase.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/test/util/FileTestCase.java b/src/test/java/org/apache/freemarker/test/util/FileTestCase.java
index 168012a..c0990ba 100644
--- a/src/test/java/org/apache/freemarker/test/util/FileTestCase.java
+++ b/src/test/java/org/apache/freemarker/test/util/FileTestCase.java
@@ -30,6 +30,8 @@ import java.io.OutputStreamWriter;
 import java.io.Reader;
 import java.io.Writer;
 import java.net.URL;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 
 import org.apache.freemarker.core.util._StringUtil;
 
@@ -60,7 +62,7 @@ public abstract class FileTestCase extends TestCase {
         try {
             final File expectedFile = getExpectedFileFor(expectedFileName);
             
-            AssertionFailedError assertionExcepton = null;
+            AssertionFailedError assertionException = null;
             boolean successful = false;
             try {
                 if (expectedFile.exists()) {
@@ -68,7 +70,7 @@ public abstract class FileTestCase extends TestCase {
                     successful = true;
                 }
             } catch (AssertionFailedError e) {
-                assertionExcepton = e;
+                assertionException = e;
             }
             
             if (!successful) {
@@ -76,8 +78,8 @@ public abstract class FileTestCase extends TestCase {
                 saveString(actualFile, actualContent);
                 reportActualFileSaved(actualFile);
                 
-                if (assertionExcepton != null) {
-                    throw assertionExcepton;
+                if (assertionException != null) {
+                    throw assertionException;
                 } else {
                     throw new FileNotFoundException(expectedFile.getPath());
                 }
@@ -106,7 +108,7 @@ public abstract class FileTestCase extends TestCase {
     }
 
     private void saveString(File actualFile, String actualContents) throws IOException {
-        Writer w = new OutputStreamWriter(new FileOutputStream(actualFile), "UTF-8");
+        Writer w = new OutputStreamWriter(new FileOutputStream(actualFile), StandardCharsets.UTF_8);
         try {
             w.write(actualContents);
         } finally {
@@ -145,30 +147,30 @@ public abstract class FileTestCase extends TestCase {
     }
 
     protected String loadFile(File f) throws IOException {
-        return TestUtil.removeTxtCopyrightComment(loadFile(f, getDefaultCharset()));
+        return TestUtil.removeTxtCopyrightComment(loadFile(f, getFileCharset()));
     }
     
-    protected String loadFile(File f, String charset) throws IOException {
+    protected String loadFile(File f, Charset charset) throws IOException {
         return loadString(new FileInputStream(f), charset);
     }
 
     protected String loadResource(String resourceName) throws IOException {
-        return loadResource(resourceName, getDefaultCharset());
+        return loadResource(resourceName, getFileCharset());
     }
     
-    protected String loadResource(String resourceName, String charset) throws IOException {
+    protected String loadResource(String resourceName, Charset charset) throws IOException {
         return loadString(new FileInputStream(new File(getTestClassDirectory(), resourceName)), charset);
     }
     
-    protected String getDefaultCharset() {
-        return "UTF-8";
+    protected Charset getFileCharset() {
+        return StandardCharsets.UTF_8;
     }
     
     protected void reportActualFileSaved(File f) {
         System.out.println("Note: Saved actual output of the failed test to here: " + f.getAbsolutePath());
     }
    
-    private static String loadString(InputStream in, String charset) throws IOException {
+    private static String loadString(InputStream in, Charset charset) throws IOException {
         Reader r = new InputStreamReader(in, charset);
         StringBuilder sb = new StringBuilder(1024);
         try {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/resources/org/apache/freemarker/manualtest/TemplateConfigurationExamples1.properties
----------------------------------------------------------------------
diff --git a/src/test/resources/org/apache/freemarker/manualtest/TemplateConfigurationExamples1.properties b/src/test/resources/org/apache/freemarker/manualtest/TemplateConfigurationExamples1.properties
index 6c33890..faf8592 100644
--- a/src/test/resources/org/apache/freemarker/manualtest/TemplateConfigurationExamples1.properties
+++ b/src/test/resources/org/apache/freemarker/manualtest/TemplateConfigurationExamples1.properties
@@ -19,7 +19,7 @@ templateConfigurations = \
     ConditionalTemplateConfigurationFactory( \
         FileExtensionMatcher("xml"), \
         TemplateConfiguration( \
-            sourceEncoding = "utf-8", \
+            sourceEncoding = Charset("utf-8"), \
             outputFormat = XMLOutputFormat() \
         ) \
     )
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/resources/org/apache/freemarker/manualtest/TemplateConfigurationExamples3.properties
----------------------------------------------------------------------
diff --git a/src/test/resources/org/apache/freemarker/manualtest/TemplateConfigurationExamples3.properties b/src/test/resources/org/apache/freemarker/manualtest/TemplateConfigurationExamples3.properties
index 27301bf..ce72fef 100644
--- a/src/test/resources/org/apache/freemarker/manualtest/TemplateConfigurationExamples3.properties
+++ b/src/test/resources/org/apache/freemarker/manualtest/TemplateConfigurationExamples3.properties
@@ -28,7 +28,7 @@ templateConfigurations = \
         ), \
         ConditionalTemplateConfigurationFactory( \
             PathGlobMatcher("mail/**"), \
-            TemplateConfiguration(sourceEncoding = "utf-8") \
+            TemplateConfiguration(sourceEncoding = Charset("utf-8")) \
         ), \
         FirstMatchTemplateConfigurationFactory( \
             ConditionalTemplateConfigurationFactory( \

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/resources/org/apache/freemarker/test/templatesuite/testcases.xml
----------------------------------------------------------------------
diff --git a/src/test/resources/org/apache/freemarker/test/templatesuite/testcases.xml b/src/test/resources/org/apache/freemarker/test/templatesuite/testcases.xml
index e38110e..4ff2437 100644
--- a/src/test/resources/org/apache/freemarker/test/templatesuite/testcases.xml
+++ b/src/test/resources/org/apache/freemarker/test/templatesuite/testcases.xml
@@ -34,7 +34,7 @@
  <!ELEMENT setting EMPTY>
      <!ATTLIST setting 
             auto_import CDATA #IMPLIED
-            input_encoding CDATA #IMPLIED
+            source_encoding CDATA #IMPLIED
             locale CDATA #IMPLIED
             object_wrapper CDATA #IMPLIED
             output_encoding CDATA #IMPLIED
@@ -52,7 +52,7 @@ Note that for the incompatible_improvements setting you can specify a list of ve
 -->
 
 <testCases>
-   <setting input_encoding="UTF-8" output_encoding="UTF-8" />
+   <setting source_encoding="UTF-8" output_encoding="UTF-8" />
    
    <testCase name="api-builtins" noOutput="true">
       <setting api_builtin_enabled="true" />
@@ -84,7 +84,7 @@ Note that for the incompatible_improvements setting you can specify a list of ve
    </testCase>
    <testCase name="include" />
    <testCase name="include2">
-      <setting input_encoding="utf-8" />
+      <setting source_encoding="utf-8" />
    </testCase>
    <testCase name="interpret"/>
    <testCase name="iterators"/>


[2/2] incubator-freemarker git commit: Settings that have contained a charset name (sourceEncoding, outputEncoding, URLEscapingCharset) are now of type Charset, not String. For string based configuration sources (such as .properties files) this means tha

Posted by dd...@apache.org.
Settings that have contained a charset name (sourceEncoding, outputEncoding, URLEscapingCharset) are now of type Charset, not String. For string based configuration sources (such as .properties files) this means that:

- Unrecognized charset names are now errors
- For recognized names the charset name will be normalized (like "latin1" becomes to "ISO-8859-1").
- In "object builder expressions" Charset values can now be constructed like `Charset("ISO-8859-5")`. Note that as the type of the settings have changed, now you can't just write something like `TemplateConfiguration(sourceEncoding = "UTF-8")`, but `TemplateConfiguration(sourceEncoding = Charset("UTF-8"))`.


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/27a62ce0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/27a62ce0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/27a62ce0

Branch: refs/heads/3
Commit: 27a62ce0158e689d0bf23b239447d6f40721ccc4
Parents: 5062b4e
Author: ddekany <dd...@apache.org>
Authored: Wed Mar 29 01:09:12 2017 +0200
Committer: ddekany <dd...@apache.org>
Committed: Wed Mar 29 01:10:08 2017 +0200

----------------------------------------------------------------------
 .../freemarker/core/ASTExpBuiltInVariable.java  |  9 ++-
 .../core/BuiltInsForStringsEncoding.java        | 30 ++++---
 .../apache/freemarker/core/Configuration.java   | 51 ++++++------
 .../org/apache/freemarker/core/Environment.java |  9 ++-
 .../MutableProcessingAndParseConfiguration.java | 13 +--
 .../core/MutableProcessingConfiguration.java    | 41 +++++-----
 .../freemarker/core/ParserConfiguration.java    |  3 +-
 .../core/ProcessingConfiguration.java           |  9 ++-
 .../org/apache/freemarker/core/Template.java    | 37 +++++----
 .../freemarker/core/TemplateConfiguration.java  | 17 ++--
 .../freemarker/core/TemplateLanguage.java       | 15 ++--
 .../core/WrongTemplateCharsetException.java     | 12 +--
 .../apache/freemarker/core/_CharsetBuilder.java | 41 ++++++++++
 .../core/_ObjectBuilderSettingEvaluator.java    | 14 +++-
 ..._ParserConfigurationWithInheritedFormat.java |  4 +-
 .../freemarker/core/debug/DebuggerClient.java   |  3 +-
 .../freemarker/core/debug/DebuggerServer.java   |  9 ++-
 .../templateresolver/TemplateLoadingResult.java |  5 +-
 .../impl/DefaultTemplateResolver.java           |  5 +-
 .../freemarker/core/util/_StringUtil.java       |  9 ++-
 .../freemarker/servlet/FreemarkerServlet.java   | 30 ++++---
 .../freemarker/servlet/jsp/TaglibFactory.java   | 14 ++--
 src/main/javacc/FTL.jj                          | 21 ++++-
 src/manual/en_US/FM3-CHANGE-LOG.txt             |  7 ++
 .../org/apache/freemarker/core/ASTPrinter.java  |  5 +-
 .../apache/freemarker/core/CamelCaseTest.java   | 29 +++----
 .../freemarker/core/ConfigurationTest.java      | 64 ++++++++-------
 .../freemarker/core/EncodingOverrideTest.java   | 31 +++-----
 .../core/ObjectBuilderSettingsTest.java         | 40 +++++++++-
 .../core/TemplateConfigurationTest.java         | 51 ++++--------
 ...igurationWithDefaltTemplateResolverTest.java | 32 ++++----
 .../core/TemplateConstructorsTest.java          | 52 +++++++-----
 .../core/TemplateGetEncodingTest.java           | 10 ++-
 .../DefaultTemplateResolverTest.java            |  8 +-
 .../manualtest/GettingStartedExample.java       |  3 +-
 .../TemplateConfigurationExamples.java          | 19 ++---
 .../servlet/FreemarkerServletTest.java          | 84 ++++++++++----------
 .../freemarker/test/ResourcesExtractor.java     |  3 +-
 .../apache/freemarker/test/TemplateTest.java    |  6 +-
 .../test/servlet/Model2TesterServlet.java       |  3 +-
 .../freemarker/test/servlet/WebAppTestCase.java |  7 +-
 .../test/templatesuite/TemplateTestCase.java    | 10 ++-
 .../freemarker/test/util/FileTestCase.java      | 26 +++---
 .../TemplateConfigurationExamples1.properties   |  2 +-
 .../TemplateConfigurationExamples3.properties   |  2 +-
 .../freemarker/test/templatesuite/testcases.xml |  6 +-
 46 files changed, 528 insertions(+), 373 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/core/ASTExpBuiltInVariable.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ASTExpBuiltInVariable.java b/src/main/java/org/apache/freemarker/core/ASTExpBuiltInVariable.java
index 2b4f756..9110fd3 100644
--- a/src/main/java/org/apache/freemarker/core/ASTExpBuiltInVariable.java
+++ b/src/main/java/org/apache/freemarker/core/ASTExpBuiltInVariable.java
@@ -19,6 +19,7 @@
 
 package org.apache.freemarker.core;
 
+import java.nio.charset.Charset;
 import java.util.Arrays;
 import java.util.Date;
 
@@ -210,12 +211,12 @@ final class ASTExpBuiltInVariable extends ASTExpression {
             return ASTDirMacro.DO_NOTHING_MACRO;
         }
         if (name == OUTPUT_ENCODING || name == OUTPUT_ENCODING_CC) {
-            String s = env.getOutputEncoding();
-            return SimpleScalar.newInstanceOrNull(s);
+            Charset encoding = env.getOutputEncoding();
+            return encoding != null ? new SimpleScalar(encoding.name()) : null;
         }
         if (name == URL_ESCAPING_CHARSET || name == URL_ESCAPING_CHARSET_CC) {
-            String s = env.getURLEscapingCharset();
-            return SimpleScalar.newInstanceOrNull(s);
+            Charset charset = env.getURLEscapingCharset();
+            return charset != null ? new SimpleScalar(charset.name()) : null;
         }
         if (name == ERROR) {
             return new SimpleScalar(env.getCurrentRecoveredErrorMessage());

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/core/BuiltInsForStringsEncoding.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/BuiltInsForStringsEncoding.java b/src/main/java/org/apache/freemarker/core/BuiltInsForStringsEncoding.java
index e3b00fb..80eb9d3 100644
--- a/src/main/java/org/apache/freemarker/core/BuiltInsForStringsEncoding.java
+++ b/src/main/java/org/apache/freemarker/core/BuiltInsForStringsEncoding.java
@@ -20,6 +20,8 @@
 package org.apache.freemarker.core;
 
 import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
 import java.util.List;
 
 import org.apache.freemarker.core.model.TemplateMethodModel;
@@ -77,8 +79,8 @@ class BuiltInsForStringsEncoding {
             }
     
             @Override
-            protected String encodeWithCharset(String cs) throws UnsupportedEncodingException {
-                return _StringUtil.URLEnc(targetAsString, cs);
+            protected String encodeWithCharset(Charset charset) throws UnsupportedEncodingException {
+                return _StringUtil.URLEnc(targetAsString, charset);
             }
             
         }
@@ -99,8 +101,8 @@ class BuiltInsForStringsEncoding {
             }
     
             @Override
-            protected String encodeWithCharset(String cs) throws UnsupportedEncodingException {
-                return _StringUtil.URLPathEnc(targetAsString, cs);
+            protected String encodeWithCharset(Charset charset) throws UnsupportedEncodingException {
+                return _StringUtil.URLPathEnc(targetAsString, charset);
             }
             
         }
@@ -143,14 +145,22 @@ class BuiltInsForStringsEncoding {
             this.env = env;
         }
         
-        protected abstract String encodeWithCharset(String cs) throws UnsupportedEncodingException;
+        protected abstract String encodeWithCharset(Charset charset) throws UnsupportedEncodingException;
     
         @Override
         public Object exec(List args) throws TemplateModelException {
             parent.checkMethodArgCount(args.size(), 1);
             try {
-                return new SimpleScalar(encodeWithCharset((String) args.get(0)));
-            } catch (UnsupportedEncodingException e) {
+                String charsetName = (String) args.get(0);
+                Charset charset = null;
+                try {
+                    charset = Charset.forName(charsetName);
+                } catch (UnsupportedCharsetException e) {
+                    throw new _TemplateModelException(e, "Wrong charset name, or charset is unsupported by the runtime "
+                            + "environment: " + _StringUtil.jQuote(charsetName));
+                }
+                return new SimpleScalar(encodeWithCharset(charset));
+            } catch (Exception e) {
                 throw new _TemplateModelException(e, "Failed to execute URL encoding.");
             }
         }
@@ -158,8 +168,8 @@ class BuiltInsForStringsEncoding {
         @Override
         public String getAsString() throws TemplateModelException {
             if (cachedResult == null) {
-                String cs = env.getEffectiveURLEscapingCharset();
-                if (cs == null) {
+                Charset charset = env.getEffectiveURLEscapingCharset();
+                if (charset == null) {
                     throw new _TemplateModelException(
                             "To do URL encoding, the framework that encloses "
                             + "FreeMarker must specify the output encoding "
@@ -172,7 +182,7 @@ class BuiltInsForStringsEncoding {
                             + "foo?url('ISO-8859-1').");
                 }
                 try {
-                    cachedResult = encodeWithCharset(cs);
+                    cachedResult = encodeWithCharset(charset);
                 } catch (UnsupportedEncodingException e) {
                     throw new _TemplateModelException(e, "Failed to execute URL encoding.");
                 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/core/Configuration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/Configuration.java b/src/main/java/org/apache/freemarker/core/Configuration.java
index 826e2d0..52bfd19 100644
--- a/src/main/java/org/apache/freemarker/core/Configuration.java
+++ b/src/main/java/org/apache/freemarker/core/Configuration.java
@@ -23,6 +23,8 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.Serializable;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.text.SimpleDateFormat;
 import java.util.Collection;
 import java.util.Collections;
@@ -88,7 +90,6 @@ import org.apache.freemarker.core.util.StandardCompress;
 import org.apache.freemarker.core.util.XmlEscape;
 import org.apache.freemarker.core.util._ClassUtil;
 import org.apache.freemarker.core.util._NullArgumentException;
-import org.apache.freemarker.core.util._SecurityUtil;
 import org.apache.freemarker.core.util._SortedArraySet;
 import org.apache.freemarker.core.util._StringUtil;
 import org.apache.freemarker.core.util._UnmodifiableCompositeSet;
@@ -126,7 +127,7 @@ import org.apache.freemarker.core.util._UnmodifiableCompositeSet;
  *       useless. (For the most common cases you can use the convenience methods,
  *       {@link #setDirectoryForTemplateLoading(File)} and {@link #setClassForTemplateLoading(Class, String)} and
  *       {@link #setClassLoaderForTemplateLoading(ClassLoader, String)} too.)
- *   <li>{@link #setEncoding(String) encoding}: The default value is system dependent, which makes it
+ *   <li>{@link #setSourceEncoding(Charset) sourceEncoding}: The default value is system dependent, which makes it
  *       fragile on servers, so it should be set explicitly, like to "UTF-8" nowadays. 
  *   <li>{@link #setTemplateExceptionHandler(TemplateExceptionHandler) template_exception_handler}: For developing
  *       HTML pages, the most convenient value is {@link TemplateExceptionHandler#HTML_DEBUG_HANDLER}. For production,
@@ -427,7 +428,7 @@ public final class Configuration extends MutableProcessingConfiguration<Configur
     private boolean templateExceptionHandlerExplicitlySet;
     private boolean logTemplateExceptionsExplicitlySet;
     private boolean localeExplicitlySet;
-    private boolean defaultEncodingExplicitlySet;
+    private boolean sourceEncodingExplicitlySet;
     private boolean timeZoneExplicitlySet;
 
     private HashMap/*<String, TemplateModel>*/ sharedVariables = new HashMap();
@@ -442,7 +443,7 @@ public final class Configuration extends MutableProcessingConfiguration<Configur
      */
     private HashMap<String, Object> rewrappableSharedVariables = null;
     
-    private String encoding = getDefaultSourceEncoding();
+    private Charset sourceEncoding = getDefaultSourceEncoding();
 
     /**
      * @deprecated Use {@link #Configuration(Version)} instead. Note that the version can be still modified later with
@@ -2032,23 +2033,23 @@ public final class Configuration extends MutableProcessingConfiguration<Configur
      * the charset of the template.
      *
      * <p>Individual templates may specify their own charset by starting with
-     * <tt>&lt;#ftl encoding="..."&gt;</tt>. However, before that's detected, at least part of template must be
+     * <tt>&lt;#ftl sourceEncoding="..."&gt;</tt>. However, before that's detected, at least part of template must be
      * decoded with some charset first, so this setting and {@linkplain #getTemplateConfigurations() template
      * configuration} still has a role.
      *
-     * <p>Defaults to the default system encoding, which can change from one server to
+     * <p>Defaults to the default system sourceEncoding, which can change from one server to
      * another, so <b>you should always set this setting</b>. If you don't know what charset your should chose,
      * {@code "UTF-8"} is usually a good choice.
      *
-     * @param encoding The name of the charset, such as {@code "UTF-8"} or {@code "ISO-8859-1"}
+     * @param sourceEncoding The charset, for example {@link StandardCharsets#UTF_8}.
      */
-    public void setEncoding(String encoding) {
-        this.encoding = encoding;
-        defaultEncodingExplicitlySet = true;
+    public void setSourceEncoding(Charset sourceEncoding) {
+        this.sourceEncoding = sourceEncoding;
+        sourceEncodingExplicitlySet = true;
     }
 
-    public String getSourceEncoding() {
-        return encoding;
+    public Charset getSourceEncoding() {
+        return sourceEncoding;
     }
 
     /**
@@ -2056,29 +2057,25 @@ public final class Configuration extends MutableProcessingConfiguration<Configur
      *
      * @since 2.3.26
      */
-    public void unsetDefaultEncoding() {
-        if (defaultEncodingExplicitlySet) {
-            setEncoding(getDefaultSourceEncoding());
-            defaultEncodingExplicitlySet = false;
+    public void unsetSourceEncoding() {
+        if (sourceEncodingExplicitlySet) {
+            setSourceEncoding(getDefaultSourceEncoding());
+            sourceEncodingExplicitlySet = false;
         }
     }
 
     /**
-     * Tells if {@link #setEncoding(String)} (or equivalent) was already called on this instance, or it just holds the
+     * Tells if {@link #setSourceEncoding(Charset)} (or equivalent) was already called on this instance, or it just holds the
      * default value.
      *
      * @since 2.3.26
      */
-    public boolean isDefaultEncodingExplicitlySet() {
-        return defaultEncodingExplicitlySet;
+    public boolean isSourceEncodingExplicitlySet() {
+        return sourceEncodingExplicitlySet;
     }
 
-    static private String getDefaultSourceEncoding() {
-        return getJVMDefaultEncoding();
-    }
-
-    static private String getJVMDefaultEncoding() {
-        return _SecurityUtil.getSystemProperty("file.encoding", "utf-8");
+    static private Charset getDefaultSourceEncoding() {
+        return Charset.defaultCharset();
     }
 
     /**
@@ -2305,9 +2302,9 @@ public final class Configuration extends MutableProcessingConfiguration<Configur
             
             if (SOURCE_ENCODING_KEY_SNAKE_CASE.equals(name) || SOURCE_ENCODING_KEY_CAMEL_CASE.equals(name)) {
                 if (JVM_DEFAULT_VALUE.equalsIgnoreCase(value)) {
-                    setEncoding(getJVMDefaultEncoding());
+                    setSourceEncoding(Charset.defaultCharset());
                 } else {
-                    setEncoding(value);
+                    setSourceEncoding(Charset.forName(value));
                 }
             } else if (LOCALIZED_LOOKUP_KEY_SNAKE_CASE.equals(name) || LOCALIZED_LOOKUP_KEY_CAMEL_CASE.equals(name)) {
                 setLocalizedLookup(_StringUtil.getYesNo(value));

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/core/Environment.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/Environment.java b/src/main/java/org/apache/freemarker/core/Environment.java
index ce95b15..6733045 100644
--- a/src/main/java/org/apache/freemarker/core/Environment.java
+++ b/src/main/java/org/apache/freemarker/core/Environment.java
@@ -24,6 +24,7 @@ import java.io.PrintWriter;
 import java.io.Serializable;
 import java.io.StringWriter;
 import java.io.Writer;
+import java.nio.charset.Charset;
 import java.sql.Time;
 import java.sql.Timestamp;
 import java.text.Collator;
@@ -185,7 +186,7 @@ public final class Environment extends MutableProcessingConfiguration<Environmen
     private int nodeNamespaceIndex;
     private String currentNodeName, currentNodeNS;
 
-    private String cachedURLEscapingCharset;
+    private Charset cachedURLEscapingCharset;
     private boolean cachedURLEscapingCharsetSet;
 
     private boolean fastInvalidReferenceExceptions;
@@ -941,7 +942,7 @@ public final class Environment extends MutableProcessingConfiguration<Environmen
     }
 
     @Override
-    public void setURLEscapingCharset(String urlEscapingCharset) {
+    public void setURLEscapingCharset(Charset urlEscapingCharset) {
         cachedURLEscapingCharsetSet = false;
         super.setURLEscapingCharset(urlEscapingCharset);
     }
@@ -952,7 +953,7 @@ public final class Environment extends MutableProcessingConfiguration<Environmen
      * change the output encoding on-the-fly.
      */
     @Override
-    public void setOutputEncoding(String outputEncoding) {
+    public void setOutputEncoding(Charset outputEncoding) {
         cachedURLEscapingCharsetSet = false;
         super.setOutputEncoding(outputEncoding);
     }
@@ -961,7 +962,7 @@ public final class Environment extends MutableProcessingConfiguration<Environmen
      * Returns the name of the charset that should be used for URL encoding. This will be <code>null</code> if the
      * information is not available. The function caches the return value, so it's quick to call it repeatedly.
      */
-    String getEffectiveURLEscapingCharset() {
+    Charset getEffectiveURLEscapingCharset() {
         if (!cachedURLEscapingCharsetSet) {
             cachedURLEscapingCharset = getURLEscapingCharset();
             if (cachedURLEscapingCharset == null) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/core/MutableProcessingAndParseConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/MutableProcessingAndParseConfiguration.java b/src/main/java/org/apache/freemarker/core/MutableProcessingAndParseConfiguration.java
index 4d7a1e1..03cfb95 100644
--- a/src/main/java/org/apache/freemarker/core/MutableProcessingAndParseConfiguration.java
+++ b/src/main/java/org/apache/freemarker/core/MutableProcessingAndParseConfiguration.java
@@ -20,6 +20,7 @@
 package org.apache.freemarker.core;
 
 import java.io.InputStream;
+import java.nio.charset.Charset;
 
 import org.apache.freemarker.core.outputformat.OutputFormat;
 import org.apache.freemarker.core.templateresolver.TemplateLoader;
@@ -38,7 +39,7 @@ public abstract class MutableProcessingAndParseConfiguration<
     private Integer autoEscapingPolicy;
     private Boolean recognizeStandardFileExtensions;
     private OutputFormat outputFormat;
-    private String sourceEncoding;
+    private Charset sourceEncoding;
     private Integer tabSize;
 
     protected MutableProcessingAndParseConfiguration(Version incompatibleImprovements) {
@@ -227,17 +228,17 @@ public abstract class MutableProcessingAndParseConfiguration<
         return recognizeStandardFileExtensions != null;
     }
 
-    public String getSourceEncoding() {
+    public Charset getSourceEncoding() {
         return sourceEncoding != null ? sourceEncoding : getDefaultSourceEncoding();
     }
 
-    protected abstract String getDefaultSourceEncoding();
+    protected abstract Charset getDefaultSourceEncoding();
 
     /**
      * The charset to be used when reading the template "file" that the {@link TemplateLoader} returns as binary
      * ({@link InputStream}). If the {@code #ftl} header specifies an charset, that will override this.
      */
-    public void setSourceEncoding(String sourceEncoding) {
+    public void setSourceEncoding(Charset sourceEncoding) {
         _NullArgumentException.check("sourceEncoding", sourceEncoding);
         this.sourceEncoding = sourceEncoding;
     }
@@ -263,10 +264,10 @@ public abstract class MutableProcessingAndParseConfiguration<
     @Override
     public int getTabSize() {
         return tabSize != null ? tabSize.intValue()
-                : getDefailtTabSize();
+                : getDefaultTabSize();
     }
 
-    protected abstract int getDefailtTabSize();
+    protected abstract int getDefaultTabSize();
 
     /**
      * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java b/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java
index eef4188..d9200b0 100644
--- a/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java
+++ b/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java
@@ -21,6 +21,7 @@ package org.apache.freemarker.core;
 
 import java.io.IOException;
 import java.io.Writer;
+import java.nio.charset.Charset;
 import java.text.NumberFormat;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
@@ -337,9 +338,9 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
     private TemplateExceptionHandler templateExceptionHandler;
     private ArithmeticEngine arithmeticEngine;
     private ObjectWrapper objectWrapper;
-    private String outputEncoding;
+    private Charset outputEncoding;
     private boolean outputEncodingSet;
-    private String urlEscapingCharset;
+    private Charset urlEscapingCharset;
     private boolean urlEscapingCharsetSet;
     private Boolean autoFlush;
     private TemplateClassResolver newBuiltinClassResolver;
@@ -1306,21 +1307,21 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
      * 
      * <p>Defaults to {@code null} (unknown).
      */
-    public void setOutputEncoding(String outputEncoding) {
+    public void setOutputEncoding(Charset outputEncoding) {
         this.outputEncoding = outputEncoding;
         outputEncodingSet = true;
     }
 
     /**
-     * Fluent API equivalent of {@link #setOutputEncoding(String)}
+     * Fluent API equivalent of {@link #setOutputEncoding(Charset)}
      */
-    public SelfT outputEncoding(String value) {
+    public SelfT outputEncoding(Charset value) {
         setOutputEncoding(value);
         return self();
     }
 
     @Override
-    public String getOutputEncoding() {
+    public Charset getOutputEncoding() {
         return outputEncodingSet
                 ? outputEncoding
                 : (parent != null ? parent.getOutputEncoding() : null);
@@ -1338,25 +1339,25 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
     
     /**
      * Sets the URL escaping charset. If not set ({@code null}), the output encoding
-     * ({@link #setOutputEncoding(String)}) will be used for URL escaping.
+     * ({@link #setOutputEncoding(Charset)}) will be used for URL escaping.
      * 
      * Defaults to {@code null}.
      */
-    public void setURLEscapingCharset(String urlEscapingCharset) {
+    public void setURLEscapingCharset(Charset urlEscapingCharset) {
         this.urlEscapingCharset = urlEscapingCharset;
         urlEscapingCharsetSet = true;
     }
 
     /**
-     * Fluent API equivalent of {@link #setURLEscapingCharset(String)}
+     * Fluent API equivalent of {@link #setURLEscapingCharset(Charset)}
      */
-    public SelfT urlEscapingCharset(String value) {
+    public SelfT urlEscapingCharset(Charset value) {
         setURLEscapingCharset(value);
         return self();
     }
 
     @Override
-    public String getURLEscapingCharset() {
+    public Charset getURLEscapingCharset() {
         return urlEscapingCharsetSet
                 ? urlEscapingCharset
                 : (parent != null ? parent.getURLEscapingCharset() : null);
@@ -1982,10 +1983,10 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
      *       as {@link #setSQLDateAndTimeTimeZone(TimeZone) setSQLDateAndTimeTimeZone(null)}.
      *       
      *   <li><p>{@code "output_encoding"}:
-     *       See {@link #setOutputEncoding(String)}.
+     *       See {@link #setOutputEncoding(Charset)}.
      *       
      *   <li><p>{@code "url_escaping_charset"}:
-     *       See {@link #setURLEscapingCharset(String)}.
+     *       See {@link #setURLEscapingCharset(Charset)}.
      *       
      *   <li><p>{@code "auto_flush"}:
      *       See {@link #setAutoFlush(boolean)}.
@@ -2088,8 +2089,8 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
      *       {@link Configuration#ENABLE_IF_SUPPORTED_AUTO_ESCAPING_POLICY}
      *       {@code "disable"} for {@link Configuration#DISABLE_AUTO_ESCAPING_POLICY}.
      *       
-     *   <li><p>{@code "encoding"}:
-     *       See {@link Configuration#setEncoding(String)}; since 2.3.26 also accepts value "JVM default"
+     *   <li><p>{@code "sourceEncoding"}:
+     *       See {@link Configuration#setSourceEncoding(Charset)}; since 2.3.26 also accepts value "JVM default"
      *       (not case sensitive) to set the Java environment default value.
      *       <br>As the default value is the system default, which can change
      *       from one server to another, <b>you should always set this!</b>
@@ -2266,7 +2267,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
      *   </li>
      *   <li>
      *     <p>{@link TimeZone} objects can be created like {@code TimeZone("UTC")}, despite that there's no a such
-     *     constructor (since 2.3.24).
+     *     constructor.
+     *   </li>
+     *   <li>
+     *     <p>{@link Charset} objects can be created like {@code Charset("ISO-8859-5")}, despite that there's no a such
+     *     constructor.
      *   </li>
      *   <li>
      *     <p>The classes and methods that the expression meant to access must be all public.
@@ -2368,10 +2373,10 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
             } else if (BOOLEAN_FORMAT_KEY_SNAKE_CASE.equals(name) || BOOLEAN_FORMAT_KEY_CAMEL_CASE.equals(name)) {
                 setBooleanFormat(value);
             } else if (OUTPUT_ENCODING_KEY_SNAKE_CASE.equals(name) || OUTPUT_ENCODING_KEY_CAMEL_CASE.equals(name)) {
-                setOutputEncoding(value);
+                setOutputEncoding(Charset.forName(value));
             } else if (URL_ESCAPING_CHARSET_KEY_SNAKE_CASE.equals(name)
                     || URL_ESCAPING_CHARSET_KEY_CAMEL_CASE.equals(name)) {
-                setURLEscapingCharset(value);
+                setURLEscapingCharset(Charset.forName(value));
             } else if (AUTO_FLUSH_KEY_SNAKE_CASE.equals(name) || AUTO_FLUSH_KEY_CAMEL_CASE.equals(name)) {
                 setAutoFlush(_StringUtil.getYesNo(value));
             } else if (SHOW_ERROR_TIPS_KEY_SNAKE_CASE.equals(name) || SHOW_ERROR_TIPS_KEY_CAMEL_CASE.equals(name)) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/core/ParserConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ParserConfiguration.java b/src/main/java/org/apache/freemarker/core/ParserConfiguration.java
index a620506..e515826 100644
--- a/src/main/java/org/apache/freemarker/core/ParserConfiguration.java
+++ b/src/main/java/org/apache/freemarker/core/ParserConfiguration.java
@@ -19,6 +19,7 @@
 package org.apache.freemarker.core;
 
 import java.io.Writer;
+import java.nio.charset.Charset;
 
 import org.apache.freemarker.core.arithmetic.ArithmeticEngine;
 import org.apache.freemarker.core.outputformat.OutputFormat;
@@ -144,6 +145,6 @@ public interface ParserConfiguration {
      * reading template files in a locale for which no explicit encoding
      * was specified. Defaults to the default system encoding.
      */
-    String getSourceEncoding();
+    Charset getSourceEncoding();
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java b/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java
index 16cbdd5..33b028e 100644
--- a/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java
+++ b/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java
@@ -20,6 +20,7 @@
 package org.apache.freemarker.core;
 
 import java.io.Writer;
+import java.nio.charset.Charset;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -202,9 +203,9 @@ public interface ProcessingConfiguration {
     boolean isObjectWrapperSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setOutputEncoding(String)}.
+     * Getter pair of {@link MutableProcessingConfiguration#setOutputEncoding(Charset)}.
      */
-    String getOutputEncoding();
+    Charset getOutputEncoding();
 
     /**
      * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
@@ -214,9 +215,9 @@ public interface ProcessingConfiguration {
     boolean isOutputEncodingSet();
 
     /**
-     * Getter pair of {@link MutableProcessingConfiguration#setURLEscapingCharset(String)}.
+     * Getter pair of {@link MutableProcessingConfiguration#setURLEscapingCharset(Charset)}.
      */
-    String getURLEscapingCharset();
+    Charset getURLEscapingCharset();
 
     /**
      * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/core/Template.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/Template.java b/src/main/java/org/apache/freemarker/core/Template.java
index e4c3669..a82c131 100644
--- a/src/main/java/org/apache/freemarker/core/Template.java
+++ b/src/main/java/org/apache/freemarker/core/Template.java
@@ -31,6 +31,7 @@ import java.io.StringReader;
 import java.io.StringWriter;
 import java.io.Writer;
 import java.lang.reflect.UndeclaredThrowableException;
+import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -82,7 +83,8 @@ public class Template extends MutableProcessingConfiguration<Template> implement
     private Map macros = new HashMap();
     private List imports = new Vector();
     private ASTElement rootElement;
-    private String sourceEncoding, defaultNS;
+    private Charset sourceEncoding;
+    String defaultNS;
     private Serializable customLookupCondition;
     private int actualTagSyntax;
     private int actualNamingConvention;
@@ -130,11 +132,11 @@ public class Template extends MutableProcessingConfiguration<Template> implement
     }
 
     /**
-     * Convenience constructor for {@link #Template(String, String, Reader, Configuration, String) Template(name, null,
+     * Convenience constructor for {@link #Template(String, String, Reader, Configuration, Charset) Template(name, null,
      * reader, cfg, sourceEncoding)}.
      */
-    public Template(String name, Reader reader, Configuration cfg, String encoding) throws IOException {
-        this(name, null, reader, cfg, encoding);
+    public Template(String name, Reader reader, Configuration cfg, Charset sourceEncoding) throws IOException {
+        this(name, null, reader, cfg, sourceEncoding);
     }
 
     /**
@@ -144,7 +146,7 @@ public class Template extends MutableProcessingConfiguration<Template> implement
      * 
      * @param name
      *            The path of the template file relatively to the (virtual) directory that you use to store the
-     *            templates (except if {@link #Template(String, String, Reader, Configuration, String) sourceName}
+     *            templates (except if {@link #Template(String, String, Reader, Configuration, Charset) sourceName}
      *            differs from it). Shouldn't start with {@code '/'}. Should use {@code '/'}, not {@code '\'}. Check
      *            {@link #getName()} to see how the name will be used. The name should be independent of the actual
      *            storage mechanism and physical location as far as possible. Even when the templates are stored
@@ -187,12 +189,13 @@ public class Template extends MutableProcessingConfiguration<Template> implement
      * @since 2.3.22
      */
    public Template(
-           String name, String sourceName, Reader reader, Configuration cfg, String sourceEncoding) throws IOException {
+           String name, String sourceName, Reader reader, Configuration cfg, Charset sourceEncoding) throws
+           IOException {
        this(name, sourceName, reader, cfg, null, sourceEncoding);
    }
    
     /**
-     * Same as {@link #Template(String, String, Reader, Configuration, String)}, but also specifies a
+     * Same as {@link #Template(String, String, Reader, Configuration, Charset)}, but also specifies a
      * {@link TemplateConfiguration}. This is mostly meant to be used by FreeMarker internally, but advanced users might
      * still find this useful.
      * 
@@ -208,20 +211,20 @@ public class Template extends MutableProcessingConfiguration<Template> implement
      *            call {@link TemplateConfiguration#apply(Template)} on the resulting {@link Template} so that
      *            {@link MutableProcessingConfiguration} settings will be set too, because this constructor only uses it as a
      *            {@link ParserConfiguration}.
-     * @param encoding
-     *            Same as in {@link #Template(String, String, Reader, Configuration, String)}.
+     * @param sourceEncoding
+     *            Same as in {@link #Template(String, String, Reader, Configuration, Charset)}.
      * 
      * @since 2.3.24
      */
    public Template(
            String name, String sourceName, Reader reader,
            Configuration cfg, ParserConfiguration customParserConfiguration,
-           String encoding) throws IOException {
-       this(name, sourceName, reader, cfg, customParserConfiguration, encoding, null);
+           Charset sourceEncoding) throws IOException {
+       this(name, sourceName, reader, cfg, customParserConfiguration, sourceEncoding, null);
     }
 
     /**
-     * Same as {@link #Template(String, String, Reader, Configuration, ParserConfiguration, String)}, but allows
+     * Same as {@link #Template(String, String, Reader, Configuration, ParserConfiguration, Charset)}, but allows
      * specifying the {@code streamToUnmarkWhenEncEstabd} {@link InputStream}.
      *
      * @param streamToUnmarkWhenEncEstabd
@@ -235,7 +238,7 @@ public class Template extends MutableProcessingConfiguration<Template> implement
    public Template(
            String name, String sourceName, Reader reader,
            Configuration cfg, ParserConfiguration customParserConfiguration,
-           String sourceEncoding, InputStream streamToUnmarkWhenEncEstabd) throws IOException, ParseException {
+           Charset sourceEncoding, InputStream streamToUnmarkWhenEncEstabd) throws IOException, ParseException {
         this(name, sourceName, cfg, customParserConfiguration);
 
        setSourceEncoding(sourceEncoding);
@@ -287,7 +290,7 @@ public class Template extends MutableProcessingConfiguration<Template> implement
     }
 
     /**
-     * Same as {@link #createPlainTextTemplate(String, String, String, Configuration, String)} with {@code null}
+     * Same as {@link #createPlainTextTemplate(String, String, String, Configuration, Charset)} with {@code null}
      * {@code sourceName} argument.
      */
     static public Template createPlainTextTemplate(String name, String content, Configuration config) {
@@ -310,7 +313,7 @@ public class Template extends MutableProcessingConfiguration<Template> implement
      * @since 2.3.22
      */
     static public Template createPlainTextTemplate(String name, String sourceName, String content, Configuration config,
-               String sourceEncoding) {
+               Charset sourceEncoding) {
         Template template;
         try {
             template = new Template(name, sourceName, new StringReader("X"), config);
@@ -572,7 +575,7 @@ public class Template extends MutableProcessingConfiguration<Template> implement
      *            The sourceEncoding that was used to read this template, or {@code null} if the source of the template
      *            already gives back text (as opposed to binary data), so no decoding with a charset was needed.
      */
-    void setSourceEncoding(String sourceEncoding) {
+    void setSourceEncoding(Charset sourceEncoding) {
         this.sourceEncoding = sourceEncoding;
     }
 
@@ -580,7 +583,7 @@ public class Template extends MutableProcessingConfiguration<Template> implement
      * The sourceEncoding that was used to read this template, or {@code null} if the source of the template
      * already gives back text (as opposed to binary data), so no decoding with a charset was needed.
      */
-    public String getSourceEncoding() {
+    public Charset getSourceEncoding() {
         return sourceEncoding;
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java b/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java
index 8b4300f..54b524e 100644
--- a/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java
+++ b/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java
@@ -19,6 +19,7 @@
 package org.apache.freemarker.core;
 
 import java.io.Reader;
+import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -47,7 +48,7 @@ import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory;
  * already found.
  * 
  * <p>
- * Note on the sourceEncoding setting {@code sourceEncoding}: See {@link #setSourceEncoding(String)}.
+ * Note on the sourceEncoding setting {@code sourceEncoding}: See {@link #setSourceEncoding(Charset)}.
  * 
  * <p>
  * Note that the result value of the reader methods (getter and "is" methods) is usually not useful unless the value of
@@ -73,7 +74,7 @@ import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory;
  * precedence.
  * </ul>
  * 
- * @see Template#Template(String, String, Reader, Configuration, ParserConfiguration, String)
+ * @see Template#Template(String, String, Reader, Configuration, ParserConfiguration, Charset)
  * 
  * @since 2.3.24
  */
@@ -87,7 +88,7 @@ public final class TemplateConfiguration extends MutableProcessingConfiguration<
     private Integer autoEscapingPolicy;
     private Boolean recognizeStandardFileExtensions;
     private OutputFormat outputFormat;
-    private String sourceEncoding;
+    private Charset sourceEncoding;
     private Integer tabSize;
 
     /**
@@ -285,7 +286,7 @@ public final class TemplateConfiguration extends MutableProcessingConfiguration<
      * 
      * <p>
      * Note that the {@code sourceEncoding} setting of the {@link Template} counts as unset if it's {@code null},
-     * even if {@code null} was set via {@link Template#setSourceEncoding(String)}.
+     * even if {@code null} was set via {@link Template#setSourceEncoding(Charset)}.
      *
      * @throws IllegalStateException
      *             If the parent configuration wasn't yet set.
@@ -558,7 +559,7 @@ public final class TemplateConfiguration extends MutableProcessingConfiguration<
         return recognizeStandardFileExtensions != null;
     }
 
-    public String getSourceEncoding() {
+    public Charset getSourceEncoding() {
         return sourceEncoding != null ? sourceEncoding : getNonNullParentConfiguration().getSourceEncoding();
     }
 
@@ -571,7 +572,7 @@ public final class TemplateConfiguration extends MutableProcessingConfiguration<
      * above behavior is not guaranteed by this class alone; you have to ensure it. Also, read the note on
      * {@code sourceEncoding} in the documentation of {@link #apply(Template)}.
      */
-    public void setSourceEncoding(String sourceEncoding) {
+    public void setSourceEncoding(Charset sourceEncoding) {
         _NullArgumentException.check("sourceEncoding", sourceEncoding);
         this.sourceEncoding = sourceEncoding;
     }
@@ -783,7 +784,7 @@ public final class TemplateConfiguration extends MutableProcessingConfiguration<
     }
 
     @Override
-    public String getOutputEncoding() {
+    public Charset getOutputEncoding() {
         try {
             return super.getOutputEncoding();
         } catch (NullPointerException e) {
@@ -793,7 +794,7 @@ public final class TemplateConfiguration extends MutableProcessingConfiguration<
     }
 
     @Override
-    public String getURLEscapingCharset() {
+    public Charset getURLEscapingCharset() {
         try {
             return super.getURLEscapingCharset();
         } catch (NullPointerException e) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/core/TemplateLanguage.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/TemplateLanguage.java b/src/main/java/org/apache/freemarker/core/TemplateLanguage.java
index 37abf56..260b35f 100644
--- a/src/main/java/org/apache/freemarker/core/TemplateLanguage.java
+++ b/src/main/java/org/apache/freemarker/core/TemplateLanguage.java
@@ -22,6 +22,7 @@ package org.apache.freemarker.core;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.Reader;
+import java.nio.charset.Charset;
 
 import org.apache.freemarker.core.util._StringUtil;
 
@@ -42,7 +43,9 @@ public abstract class TemplateLanguage {
         }
 
         @Override
-        public Template parse(String name, String sourceName, Reader reader, Configuration cfg, ParserConfiguration customParserConfiguration, String encoding, InputStream streamToUnmarkWhenEncEstabd) throws IOException, ParseException {
+        public Template parse(String name, String sourceName, Reader reader, Configuration cfg, ParserConfiguration
+                customParserConfiguration, Charset encoding, InputStream streamToUnmarkWhenEncEstabd) throws
+                IOException, ParseException {
             return new Template(name, sourceName, reader, cfg, customParserConfiguration,
                     encoding, streamToUnmarkWhenEncEstabd);
         }
@@ -55,7 +58,9 @@ public abstract class TemplateLanguage {
         }
 
         @Override
-        public Template parse(String name, String sourceName, Reader reader, Configuration cfg, ParserConfiguration customParserConfiguration, String encoding, InputStream streamToUnmarkWhenEncEstabd) throws IOException, ParseException {
+        public Template parse(String name, String sourceName, Reader reader, Configuration cfg, ParserConfiguration
+                customParserConfiguration, Charset encoding, InputStream streamToUnmarkWhenEncEstabd)
+                throws IOException, ParseException {
             // Read the contents into a StringWriter, then construct a single-text-block template from it.
             final StringBuilder sb = new StringBuilder();
             final char[] buf = new char[4096];
@@ -77,18 +82,18 @@ public abstract class TemplateLanguage {
 
     /**
      * Returns if the template can specify its own charset inside the template. If so, {@link #parse(String, String,
-     * Reader, Configuration, ParserConfiguration, String, InputStream)} can throw
+     * Reader, Configuration, ParserConfiguration, Charset, InputStream)} can throw
      * {@link WrongTemplateCharsetException}, and it might gets a non-{@code null} for the {@link InputStream}
      * parameter.
      */
     public abstract boolean getCanSpecifyCharsetInContent();
 
     /**
-     * See {@link Template#Template(String, String, Reader, Configuration, ParserConfiguration, String, InputStream)}.
+     * See {@link Template#Template(String, String, Reader, Configuration, ParserConfiguration, Charset, InputStream)}.
      */
     public abstract Template parse(String name, String sourceName, Reader reader,
                                    Configuration cfg, ParserConfiguration customParserConfiguration,
-                                   String encoding, InputStream streamToUnmarkWhenEncEstabd)
+                                   Charset encoding, InputStream streamToUnmarkWhenEncEstabd)
             throws IOException, ParseException;
 
     public String getName() {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/core/WrongTemplateCharsetException.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/WrongTemplateCharsetException.java b/src/main/java/org/apache/freemarker/core/WrongTemplateCharsetException.java
index 18d3ed4..799efb4 100644
--- a/src/main/java/org/apache/freemarker/core/WrongTemplateCharsetException.java
+++ b/src/main/java/org/apache/freemarker/core/WrongTemplateCharsetException.java
@@ -19,6 +19,8 @@
 
 package org.apache.freemarker.core;
 
+import java.nio.charset.Charset;
+
 /**
  * Thrown by the {@link Template} constructors that specify a non-{@code null} encoding whoch doesn't match the
  * encoding specified in the {@code #ftl} header of the template.
@@ -26,13 +28,13 @@ package org.apache.freemarker.core;
 public class WrongTemplateCharsetException extends ParseException {
     private static final long serialVersionUID = 1L;
 
-    private final String templateSpecifiedEncoding;
-    private final String constructorSpecifiedEncoding;
+    private final Charset templateSpecifiedEncoding;
+    private final Charset constructorSpecifiedEncoding;
 
     /**
      * @since 2.3.22
      */
-    public WrongTemplateCharsetException(String templateSpecifiedEncoding, String constructorSpecifiedEncoding) {
+    public WrongTemplateCharsetException(Charset templateSpecifiedEncoding, Charset constructorSpecifiedEncoding) {
         this.templateSpecifiedEncoding = templateSpecifiedEncoding;
         this.constructorSpecifiedEncoding = constructorSpecifiedEncoding;
     }
@@ -47,14 +49,14 @@ public class WrongTemplateCharsetException extends ParseException {
     /**
      * @since 2.3.22
      */
-    public String getTemplateSpecifiedEncoding() {
+    public Charset getTemplateSpecifiedEncoding() {
         return templateSpecifiedEncoding;
     }
 
     /**
      * @since 2.3.22
      */
-    public String getConstructorSpecifiedEncoding() {
+    public Charset getConstructorSpecifiedEncoding() {
         return constructorSpecifiedEncoding;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/core/_CharsetBuilder.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/_CharsetBuilder.java b/src/main/java/org/apache/freemarker/core/_CharsetBuilder.java
new file mode 100644
index 0000000..3234de8
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/core/_CharsetBuilder.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.freemarker.core;
+
+import java.nio.charset.Charset;
+
+import org.apache.freemarker.core.util._NullArgumentException;
+
+/**
+ * For internal use only; don't depend on this, there's no backward compatibility guarantee at all!
+ */
+public class _CharsetBuilder {
+
+    private final String name;
+
+    public _CharsetBuilder(String name) {
+        _NullArgumentException.check(name);
+        this.name = name;
+    }
+
+    public Charset build() {
+        return Charset.forName(name);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/core/_ObjectBuilderSettingEvaluator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/_ObjectBuilderSettingEvaluator.java b/src/main/java/org/apache/freemarker/core/_ObjectBuilderSettingEvaluator.java
index 2769e49..c817517 100644
--- a/src/main/java/org/apache/freemarker/core/_ObjectBuilderSettingEvaluator.java
+++ b/src/main/java/org/apache/freemarker/core/_ObjectBuilderSettingEvaluator.java
@@ -681,8 +681,18 @@ public class _ObjectBuilderSettingEvaluator {
             addWithSimpleName(SHORTHANDS, UndefinedOutputFormat.class);
             
             addWithSimpleName(SHORTHANDS, Locale.class);
-            String tzbClassName = _TimeZoneBuilder.class.getName();
-            SHORTHANDS.put("TimeZone", tzbClassName.substring(0, tzbClassName.length() - 7));
+
+            {
+                String tzbClassName = _TimeZoneBuilder.class.getName();
+                SHORTHANDS.put("TimeZone",
+                        tzbClassName.substring(0, tzbClassName.length() - BUILDER_CLASS_POSTFIX_2.length()));
+            }
+
+            {
+                String csClassName = _CharsetBuilder.class.getName();
+                SHORTHANDS.put("Charset",
+                        csClassName.substring(0, csClassName.length() - BUILDER_CLASS_POSTFIX_2.length()));
+            }
 
             // For accessing static fields:
             addWithSimpleName(SHORTHANDS, Configuration.class);

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/core/_ParserConfigurationWithInheritedFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/_ParserConfigurationWithInheritedFormat.java b/src/main/java/org/apache/freemarker/core/_ParserConfigurationWithInheritedFormat.java
index 78acde4..bfaf93f 100644
--- a/src/main/java/org/apache/freemarker/core/_ParserConfigurationWithInheritedFormat.java
+++ b/src/main/java/org/apache/freemarker/core/_ParserConfigurationWithInheritedFormat.java
@@ -18,6 +18,8 @@
  */
 package org.apache.freemarker.core;
 
+import java.nio.charset.Charset;
+
 import org.apache.freemarker.core.arithmetic.ArithmeticEngine;
 import org.apache.freemarker.core.outputformat.OutputFormat;
 
@@ -127,7 +129,7 @@ public final class _ParserConfigurationWithInheritedFormat implements ParserConf
         return wrappedPCfg.isTabSizeSet();
     }
 
-    public String getSourceEncoding() {
+    public Charset getSourceEncoding() {
         return wrappedPCfg.getSourceEncoding();
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/core/debug/DebuggerClient.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/debug/DebuggerClient.java b/src/main/java/org/apache/freemarker/core/debug/DebuggerClient.java
index a4612e2..2af3136 100644
--- a/src/main/java/org/apache/freemarker/core/debug/DebuggerClient.java
+++ b/src/main/java/org/apache/freemarker/core/debug/DebuggerClient.java
@@ -24,6 +24,7 @@ import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.net.InetAddress;
 import java.net.Socket;
+import java.nio.charset.StandardCharsets;
 import java.rmi.RemoteException;
 import java.rmi.server.RemoteObject;
 import java.security.MessageDigest;
@@ -71,7 +72,7 @@ public class DebuggerClient {
                 }
                 byte[] challenge = (byte[]) in.readObject();
                 MessageDigest md = MessageDigest.getInstance("SHA");
-                md.update(password.getBytes("UTF-8"));
+                md.update(password.getBytes(StandardCharsets.UTF_8));
                 md.update(challenge);
                 out.writeObject(md.digest());
                 return new LocalDebuggerProxy((Debugger) in.readObject());

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/core/debug/DebuggerServer.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/debug/DebuggerServer.java b/src/main/java/org/apache/freemarker/core/debug/DebuggerServer.java
index d142d16..29fa199 100644
--- a/src/main/java/org/apache/freemarker/core/debug/DebuggerServer.java
+++ b/src/main/java/org/apache/freemarker/core/debug/DebuggerServer.java
@@ -23,16 +23,16 @@ import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
-import java.io.UnsupportedEncodingException;
 import java.net.ServerSocket;
 import java.net.Socket;
+import java.nio.charset.StandardCharsets;
+import java.nio.charset.UnsupportedCharsetException;
 import java.security.MessageDigest;
 import java.security.SecureRandom;
 import java.util.Arrays;
 import java.util.Random;
 
 import org.apache.freemarker.core._CoreLogs;
-import org.apache.freemarker.core.debug.Debugger;
 import org.apache.freemarker.core.util.UndeclaredThrowableException;
 import org.apache.freemarker.core.util._SecurityUtil;
 import org.slf4j.Logger;
@@ -56,8 +56,9 @@ class DebuggerServer {
     public DebuggerServer(Serializable debuggerStub) {
         port = _SecurityUtil.getSystemProperty("org.apache.freemarker.core.debug.port", Debugger.DEFAULT_PORT).intValue();
         try {
-            password = _SecurityUtil.getSystemProperty("org.apache.freemarker.core.debug.password", "").getBytes("UTF-8");
-        } catch (UnsupportedEncodingException e) {
+            password = _SecurityUtil.getSystemProperty("org.apache.freemarker.core.debug.password", "").getBytes(
+                    StandardCharsets.UTF_8);
+        } catch (UnsupportedCharsetException e) {
             throw new UndeclaredThrowableException(e);
         }
         this.debuggerStub = debuggerStub;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/core/templateresolver/TemplateLoadingResult.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/templateresolver/TemplateLoadingResult.java b/src/main/java/org/apache/freemarker/core/templateresolver/TemplateLoadingResult.java
index 6bed700..e1a9490 100644
--- a/src/main/java/org/apache/freemarker/core/templateresolver/TemplateLoadingResult.java
+++ b/src/main/java/org/apache/freemarker/core/templateresolver/TemplateLoadingResult.java
@@ -23,6 +23,7 @@ import java.io.BufferedReader;
 import java.io.InputStream;
 import java.io.Reader;
 import java.io.Serializable;
+import java.nio.charset.Charset;
 import java.util.Date;
 
 import org.apache.freemarker.core.Configuration;
@@ -94,8 +95,8 @@ public final class TemplateLoadingResult {
      * @param templateConfiguration
      *            Usually {@code null}, as usually the backing storage mechanism doesn't store such information; see
      *            {@link #getTemplateConfiguration()}. The most probable application is supplying the charset (encoding)
-     *            used by the {@link InputStream} (via {@link TemplateConfiguration#setSourceEncoding(String)}), but only
-     *            do that if the storage mechanism really knows what the charset is.
+     *            used by the {@link InputStream} (via {@link TemplateConfiguration#setSourceEncoding(Charset)}), but
+     *            only do that if the storage mechanism really knows what the charset is.
      */
     public TemplateLoadingResult(TemplateLoadingSource source, Serializable version, InputStream inputStream,
             TemplateConfiguration templateConfiguration) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateResolver.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateResolver.java b/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateResolver.java
index 666ef58..537b4eb 100644
--- a/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateResolver.java
+++ b/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateResolver.java
@@ -26,6 +26,7 @@ import java.io.InputStreamReader;
 import java.io.Reader;
 import java.io.Serializable;
 import java.lang.reflect.Method;
+import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
@@ -551,7 +552,7 @@ public class DefaultTemplateResolver extends TemplateResolver {
         if (tc != null && tc.isLocaleSet()) {
             locale = tc.getLocale();
         }
-        String initialEncoding = tc != null ? tc.getSourceEncoding() : config.getSourceEncoding();
+        Charset initialEncoding = tc != null ? tc.getSourceEncoding() : config.getSourceEncoding();
         TemplateLanguage templateLanguage = tc != null ? tc.getTemplateLanguage() : config .getTemplateLanguage();
 
         Template template;
@@ -592,7 +593,7 @@ public class DefaultTemplateResolver extends TemplateResolver {
                     template = templateLanguage.parse(name, sourceName, reader, config, tc,
                             initialEncoding, markedInputStream);
                 } catch (WrongTemplateCharsetException charsetException) {
-                    final String templateSpecifiedEncoding = charsetException.getTemplateSpecifiedEncoding();
+                    final Charset templateSpecifiedEncoding = charsetException.getTemplateSpecifiedEncoding();
 
                     if (inputStream != null) {
                         // We restart InputStream to re-decode it with the new charset.

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/core/util/_StringUtil.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/util/_StringUtil.java b/src/main/java/org/apache/freemarker/core/util/_StringUtil.java
index f842aff..2827c84 100644
--- a/src/main/java/org/apache/freemarker/core/util/_StringUtil.java
+++ b/src/main/java/org/apache/freemarker/core/util/_StringUtil.java
@@ -22,6 +22,7 @@ package org.apache.freemarker.core.util;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.io.Writer;
+import java.nio.charset.Charset;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
@@ -314,23 +315,23 @@ public class _StringUtil {
      * URL encoding (like%20this) for query parameter values, path <em>segments</em>, fragments; this encodes all
      * characters that are reserved anywhere.
      */
-    public static String URLEnc(String s, String charset) throws UnsupportedEncodingException {
+    public static String URLEnc(String s, Charset charset) throws UnsupportedEncodingException {
         return URLEnc(s, charset, false);
     }
     
     /**
-     * Like {@link #URLEnc(String, String)} but doesn't escape the slash character ({@code /}).
+     * Like {@link #URLEnc(String, Charset)} but doesn't escape the slash character ({@code /}).
      * This can be used to encode a path only if you know that no folder or file name will contain {@code /}
      * character (not in the path, but in the name itself), which usually stands, as the commonly used OS-es don't
      * allow that.
      * 
      * @since 2.3.21
      */
-    public static String URLPathEnc(String s, String charset) throws UnsupportedEncodingException {
+    public static String URLPathEnc(String s, Charset charset) throws UnsupportedEncodingException {
         return URLEnc(s, charset, true);
     }
     
-    private static String URLEnc(String s, String charset, boolean keepSlash)
+    private static String URLEnc(String s, Charset charset, boolean keepSlash)
             throws UnsupportedEncodingException {
         int ln = s.length();
         int i;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java b/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
index 5260b86..3b67622 100644
--- a/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
+++ b/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
@@ -212,16 +212,16 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
  * template usually just inherits that from the {@link Configuration}), and if that's not set, then reads the source
  * charset of the template, just like {@value #INIT_PARAM_VALUE_LEGACY}, and if that's {@code null} (which happens if
  * the template was loaded from a non-binary source) then it will be UTF-8. Then it passes the charset acquired this way
- * to {@link HttpServletResponse#setCharacterEncoding(String)} and {@link Environment#setOutputEncoding(String)}. (It
+ * to {@link HttpServletResponse#setCharacterEncoding(String)} and {@link Environment#setOutputEncoding(Charset)}. (It
  * doesn't call the legacy {@link HttpServletResponse#setContentType(String)} API to set the charset.) (Note that if the
  * template has a {@code content_type} template attribute (which is deprecated) that specifies a charset, it will be
  * used as the output charset of that template.)
  * <li>{@value #INIT_PARAM_VALUE_DO_NOT_SET}: {@link FreemarkerServlet} will not set the {@link HttpServletResponse}
- * "character encoding". It will still call {@link Environment#setOutputEncoding(String)}, so that the running template
+ * "character encoding". It will still call {@link Environment#setOutputEncoding(Charset)}, so that the running template
  * will be aware of the charset used for the output.
  * <li>{@value #INIT_PARAM_VALUE_FORCE_PREFIX} + charset name, for example {@code force UTF-8}: The output charset will
  * be the one specified after "force" + space, regardless of everything. The charset specified this way is passed to
- * {@link HttpServletResponse#setCharacterEncoding(String)} and {@link Environment#setOutputEncoding(String)}. If the
+ * {@link HttpServletResponse#setCharacterEncoding(String)} and {@link Environment#setOutputEncoding(Charset)}. If the
  * charset name is not recognized by Java, the servlet initialization will fail.
  * </ul>
  *
@@ -631,7 +631,7 @@ public class FreemarkerServlet extends HttpServlet {
                         throw new ConflictingInitParamsException(
                                 Configuration.SOURCE_ENCODING_KEY, DEPR_INITPARAM_ENCODING);
                     }
-                    config.setEncoding(value);
+                    config.setSourceEncoding(Charset.forName(value));
                 } else if (name.equals(DEPR_INITPARAM_TEMPLATE_DELAY)) { // BC
                     if (getInitParameter(Configuration.TEMPLATE_UPDATE_DELAY_KEY) != null) {
                         throw new ConflictingInitParamsException(
@@ -857,7 +857,7 @@ public class FreemarkerServlet extends HttpServlet {
             // Using the Servlet 2.4 way of setting character encoding.
             if (responseCharacterEncoding != ResponseCharacterEncoding.FORCE_CHARSET) {
                 if (!tempSpecContentTypeContainsCharset) {
-                    response.setCharacterEncoding(getOutputEncodingForTemplate(template));
+                    response.setCharacterEncoding(getOutputEncodingForTemplate(template).name());
                 }
             } else {
                 response.setCharacterEncoding(forcedResponseCharacterEncoding.name());
@@ -878,8 +878,18 @@ public class FreemarkerServlet extends HttpServlet {
                     // Process the template
                     Environment env = template.createProcessingEnvironment(model, response.getWriter());
                     if (responseCharacterEncoding != ResponseCharacterEncoding.LEGACY) {
-                        String actualOutputCharset = response.getCharacterEncoding();
-                        if (actualOutputCharset != null) {
+                        String actualOutputCharsetName = response.getCharacterEncoding();
+                        if (actualOutputCharsetName != null) {
+                            Charset actualOutputCharset = null;
+                            try {
+                                actualOutputCharset = Charset.forName(actualOutputCharsetName);
+                            } catch (Exception e) {
+                                throw new IllegalStateException(
+                                        "Failed to resolve charset name returned by "
+                                        + " HttpServletResponse.getCharacterEncoding(): "
+                                        + _StringUtil.jQuote(actualOutputCharsetName),
+                                        e);
+                            }
                             env.setOutputEncoding(actualOutputCharset);
                         }
                     }
@@ -917,13 +927,13 @@ public class FreemarkerServlet extends HttpServlet {
         env.process();
     }
 
-    private String getOutputEncodingForTemplate(Template template) {
-        String outputEncoding = responseCharacterEncoding == ResponseCharacterEncoding.LEGACY ? null
+    private Charset getOutputEncodingForTemplate(Template template) {
+        Charset outputEncoding = responseCharacterEncoding == ResponseCharacterEncoding.LEGACY ? null
                 : template.getOutputEncoding();
         // [FM3] Don't use template.getSourceEncoding() here; it might can't encode the dynamic values inserted.
         return outputEncoding != null ? outputEncoding
                 : template.getSourceEncoding() != null ? template.getSourceEncoding()
-                : StandardCharsets.UTF_8.name();
+                : StandardCharsets.UTF_8;
     }
 
     private ContentType getTemplateSpecificContentType(final Template template) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/java/org/apache/freemarker/servlet/jsp/TaglibFactory.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/servlet/jsp/TaglibFactory.java b/src/main/java/org/apache/freemarker/servlet/jsp/TaglibFactory.java
index ec4a5d0..4452fa1 100644
--- a/src/main/java/org/apache/freemarker/servlet/jsp/TaglibFactory.java
+++ b/src/main/java/org/apache/freemarker/servlet/jsp/TaglibFactory.java
@@ -37,6 +37,7 @@ import java.net.URL;
 import java.net.URLConnection;
 import java.net.URLDecoder;
 import java.net.URLEncoder;
+import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Enumeration;
@@ -71,7 +72,6 @@ import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
 import org.apache.freemarker.core.util.BugException;
 import org.apache.freemarker.core.util._ClassUtil;
 import org.apache.freemarker.core.util._NullArgumentException;
-import org.apache.freemarker.core.util._SecurityUtil;
 import org.apache.freemarker.core.util._StringUtil;
 import org.apache.freemarker.servlet.FreemarkerServlet;
 import org.apache.freemarker.servlet.HttpRequestHashModel;
@@ -122,8 +122,6 @@ public class TaglibFactory implements TemplateHashModel {
     private static final String DEFAULT_TLD_RESOURCE_PATH = META_INF_ABS_PATH + "taglib.tld";
     private static final String JAR_URL_ENTRY_PATH_START = "!/";
 
-    private static final String PLATFORM_FILE_ENCODING = _SecurityUtil.getSystemProperty("file.encoding", "utf-8");
-
     private final ServletContext servletContext;
 
     private ObjectWrapper objectWrapper;
@@ -971,7 +969,7 @@ public class TaglibFactory implements TemplateHashModel {
             relativeEntryPath = relativeEntryPath.substring(1);
         }
         try {
-            return new URL(jarBaseEntryUrl, _StringUtil.URLPathEnc(relativeEntryPath, PLATFORM_FILE_ENCODING));
+            return new URL(jarBaseEntryUrl, _StringUtil.URLPathEnc(relativeEntryPath, Charset.defaultCharset()));
         } catch (UnsupportedEncodingException e) {
             throw new BugException();
         }
@@ -999,7 +997,7 @@ public class TaglibFactory implements TemplateHashModel {
     }
 
     /**
-     * Converts an URL to a {@code File} object, if the URL format (scheme) makes is possible.
+     * Converts an URL to a {@code File} object, if the URL format (scheme) makes it possible.
      */
     private File urlToFileOrNull(URL url) {
         if (test_emulateNoUrlToFileConversions) {
@@ -1018,7 +1016,7 @@ public class TaglibFactory implements TemplateHashModel {
             // URL.getFile() doesn't decode %XX-s (used for spaces and non-US-ASCII letters usually), so we do.
             // As it was originally created for a file somewhere, we hope that it uses the platform default encoding.
             try {
-                filePath = URLDecoder.decode(url.getFile(), PLATFORM_FILE_ENCODING);
+                filePath = URLDecoder.decode(url.getFile(), Charset.defaultCharset().name());
             } catch (UnsupportedEncodingException e2) {
                 throw new BugException(e2);
             }
@@ -1066,7 +1064,7 @@ public class TaglibFactory implements TemplateHashModel {
                     + JAR_URL_ENTRY_PATH_START
                     + URLEncoder.encode(
                             entryPath.startsWith("/") ? entryPath.substring(1) : entryPath,
-                            PLATFORM_FILE_ENCODING));
+                            Charset.defaultCharset().name()));
         } catch (Exception e) {
             LOG.error("Couldn't get URL for serlvetContext resource "
                         + _StringUtil.jQuoteNoXSS(servletContextJarFilePath)
@@ -1350,7 +1348,7 @@ public class TaglibFactory implements TemplateHashModel {
                 entryPath = normalizeJarEntryPath(
                         URLDecoder.decode(
                                 urlEF.substring(sepIdx + JAR_URL_ENTRY_PATH_START.length()),
-                                PLATFORM_FILE_ENCODING),
+                                Charset.defaultCharset().name()),
                         false);
             }
             

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/main/javacc/FTL.jj
----------------------------------------------------------------------
diff --git a/src/main/javacc/FTL.jj b/src/main/javacc/FTL.jj
index 8af611e..0e79431 100644
--- a/src/main/javacc/FTL.jj
+++ b/src/main/javacc/FTL.jj
@@ -37,6 +37,8 @@ import org.apache.freemarker.core.model.impl.*;
 import org.apache.freemarker.core.util.*;
 import java.io.*;
 import java.util.*;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
 
 /**
  * This class is generated by JavaCC from a grammar file.
@@ -3887,13 +3889,24 @@ void HeaderElement() :
                         } catch (TemplateModelException tme) {}
                     }
                     if (template != null) {
-                        if (ks.equalsIgnoreCase("sourceEncoding")) {
+                        if (ks.equalsIgnoreCase("encoding")) {
                             if (vs == null) {
                                 throw new ParseException("Expected a string constant for \"" + ks + "\".", exp);
                             }
-                            if (template.getSourceEncoding() != null && vs != null
-                                    && !template.getSourceEncoding().equalsIgnoreCase(vs)) {
-                                throw new WrongTemplateCharsetException(vs, template.getSourceEncoding());
+                            Charset encoding;
+                            try {
+                                encoding = Charset.forName(vs);
+                            } catch (UnsupportedCharsetException e) {
+                                throw new ParseException("Unknown charset (check name, or ensure that the"
+                                        + "charset is known by the runtime environment): " + vs,
+                                        exp);
+                            } catch (Exception e) {
+                                throw new ParseException("Failed resolve charset name: " + vs, exp, e
+                                        .getCause());
+                            }
+                            if (template.getSourceEncoding() != null
+                                    && !template.getSourceEncoding().equals(encoding)) {
+                                throw new WrongTemplateCharsetException(encoding, template.getSourceEncoding());
                             }
                             // There will be no WrongTemplateCharsetException exception, release mark buffer:
                             if (streamToUnmarkWhenEncEstabd != null) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/manual/en_US/FM3-CHANGE-LOG.txt
----------------------------------------------------------------------
diff --git a/src/manual/en_US/FM3-CHANGE-LOG.txt b/src/manual/en_US/FM3-CHANGE-LOG.txt
index bcab8e5..2e10077 100644
--- a/src/manual/en_US/FM3-CHANGE-LOG.txt
+++ b/src/manual/en_US/FM3-CHANGE-LOG.txt
@@ -187,3 +187,10 @@ the FreeMarer 3 changelog here:
   - Renamed Configuration.defaultEncoding to sourceEncoding, also added sourceEncoding to ParserConfiguration, and renamed
     TemplateConfiguration.encoding and Template.encoding to sourceEncoding. (Before this, defaultEncoding was exclusive
     to Configuration, but now it's like any other ParserConfiguration setting that can be overidden on the 3 levels.)
+- Settings that have contained a charset name (sourceEncoding, outputEncoding, URLEscapingCharset) are now of type Charset,
+  not String. For string based configuration sources (such as .properties files) this means that:
+  - Unrecognized charset names are now errors
+  - For recognized names the charset name will be normalized (like "latin1" becomes to "ISO-8859-1").
+  - In "object builder expressions" Charset values can now be constructed like `Charset("ISO-8859-5")`.
+    Note that as the type of the settings have changed, now you can't just write something like
+    `TemplateConfiguration(sourceEncoding = "UTF-8")`, but `TemplateConfiguration(sourceEncoding = Charset("UTF-8"))`.

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/java/org/apache/freemarker/core/ASTPrinter.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/core/ASTPrinter.java b/src/test/java/org/apache/freemarker/core/ASTPrinter.java
index 10701cf..ddd8e9b 100644
--- a/src/test/java/org/apache/freemarker/core/ASTPrinter.java
+++ b/src/test/java/org/apache/freemarker/core/ASTPrinter.java
@@ -34,6 +34,7 @@ import java.nio.ByteBuffer;
 import java.nio.charset.CharacterCodingException;
 import java.nio.charset.Charset;
 import java.nio.charset.CodingErrorAction;
+import java.nio.charset.StandardCharsets;
 import java.util.Enumeration;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
@@ -180,9 +181,9 @@ public class ASTPrinter {
         }
         
         try {
-            return decode(buffer, Charset.forName("UTF-8"));
+            return decode(buffer, StandardCharsets.UTF_8);
         } catch (CharacterCodingException e) {
-            return decode(buffer, Charset.forName("ISO-8859-1"));
+            return decode(buffer, StandardCharsets.ISO_8859_1);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/27a62ce0/src/test/java/org/apache/freemarker/core/CamelCaseTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/core/CamelCaseTest.java b/src/test/java/org/apache/freemarker/core/CamelCaseTest.java
index a3da802..7c07127 100644
--- a/src/test/java/org/apache/freemarker/core/CamelCaseTest.java
+++ b/src/test/java/org/apache/freemarker/core/CamelCaseTest.java
@@ -21,6 +21,7 @@ package org.apache.freemarker.core;
 import static org.junit.Assert.*;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Locale;
@@ -36,8 +37,8 @@ public class CamelCaseTest extends TemplateTest {
 
     @Test
     public void camelCaseSpecialVars() throws IOException, TemplateException {
-        getConfiguration().setOutputEncoding("utf-8");
-        getConfiguration().setURLEscapingCharset("iso-8859-1");
+        getConfiguration().setOutputEncoding(StandardCharsets.UTF_8);
+        getConfiguration().setURLEscapingCharset(StandardCharsets.ISO_8859_1);
         getConfiguration().setLocale(Locale.GERMANY);
         assertOutput("${.dataModel?isHash?c}", "true");
         assertOutput("${.data_model?is_hash?c}", "true");
@@ -49,12 +50,12 @@ public class CamelCaseTest extends TemplateTest {
         assertOutput("${.current_template_name!'null'}", "null");
         assertOutput("${.mainTemplateName!'null'}", "null");
         assertOutput("${.main_template_name!'null'}", "null");
-        assertOutput("${.outputEncoding}", "utf-8");
-        assertOutput("${.output_encoding}", "utf-8");
+        assertOutput("${.outputEncoding}", StandardCharsets.UTF_8.name());
+        assertOutput("${.output_encoding}", StandardCharsets.UTF_8.name());
         assertOutput("${.outputFormat}", UndefinedOutputFormat.INSTANCE.getName());
         assertOutput("${.output_format}", UndefinedOutputFormat.INSTANCE.getName());
-        assertOutput("${.urlEscapingCharset}", "iso-8859-1");
-        assertOutput("${.url_escaping_charset}", "iso-8859-1");
+        assertOutput("${.urlEscapingCharset}", StandardCharsets.ISO_8859_1.name());
+        assertOutput("${.url_escaping_charset}", StandardCharsets.ISO_8859_1.name());
         assertOutput("${.currentNode!'-'}", "-");
         assertOutput("${.current_node!'-'}", "-");
     }
@@ -86,7 +87,7 @@ public class CamelCaseTest extends TemplateTest {
     
     @Test
     public void camelCaseFtlHeaderParameters() throws IOException, TemplateException {
-        getConfiguration().setOutputEncoding("utf-8");
+        getConfiguration().setOutputEncoding(StandardCharsets.UTF_8);
         
         assertOutput(
                 "<#ftl "
@@ -118,18 +119,18 @@ public class CamelCaseTest extends TemplateTest {
         
         getConfiguration().setNamingConvention(Configuration.CAMEL_CASE_NAMING_CONVENTION);
         assertErrorContains("<#ftl strip_whitespace=true>", "naming convention");
-        assertOutput("<#ftl stripWhitespace=true>${.outputEncoding}", "utf-8");
+        assertOutput("<#ftl stripWhitespace=true>${.outputEncoding}", StandardCharsets.UTF_8.name());
         
         getConfiguration().setNamingConvention(Configuration.LEGACY_NAMING_CONVENTION);
         assertErrorContains("<#ftl stripWhitespace=true>", "naming convention");
-        assertOutput("<#ftl strip_whitespace=true>${.output_encoding}", "utf-8");
+        assertOutput("<#ftl strip_whitespace=true>${.output_encoding}", StandardCharsets.UTF_8.name());
         
         getConfiguration().setNamingConvention(Configuration.AUTO_DETECT_NAMING_CONVENTION);
-        assertOutput("<#ftl stripWhitespace=true>${.outputEncoding}", "utf-8");
-        assertOutput("<#ftl encoding='iso-8859-1' stripWhitespace=true>${.outputEncoding}", "utf-8");
-        assertOutput("<#ftl stripWhitespace=true encoding='iso-8859-1'>${.outputEncoding}", "utf-8");
-        assertOutput("<#ftl encoding='iso-8859-1' strip_whitespace=true>${.output_encoding}", "utf-8");
-        assertOutput("<#ftl strip_whitespace=true encoding='iso-8859-1'>${.output_encoding}", "utf-8");
+        assertOutput("<#ftl stripWhitespace=true>${.outputEncoding}", StandardCharsets.UTF_8.name());
+        assertOutput("<#ftl encoding='iso-8859-1' stripWhitespace=true>${.outputEncoding}", StandardCharsets.UTF_8.name());
+        assertOutput("<#ftl stripWhitespace=true encoding='iso-8859-1'>${.outputEncoding}", StandardCharsets.UTF_8.name());
+        assertOutput("<#ftl encoding='iso-8859-1' strip_whitespace=true>${.output_encoding}", StandardCharsets.UTF_8.name());
+        assertOutput("<#ftl strip_whitespace=true encoding='iso-8859-1'>${.output_encoding}", StandardCharsets.UTF_8.name());
     }
     
     @Test