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/20 17:32:25 UTC

[1/2] incubator-freemarker git commit: - Configuration.getTemplate has no "encoding" parameter anymore. Similarly #include has no "encoding" parameter either. The charset of templates can be specified via Configuration.defaultEncoding and Configuration.t

Repository: incubator-freemarker
Updated Branches:
  refs/heads/3 e365f11bd -> f6a693c57


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/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
new file mode 100644
index 0000000..700e718
--- /dev/null
+++ b/src/test/java/org/apache/freemarker/core/TemplateConfigurationWithDefaltTemplateResolverTest.java
@@ -0,0 +1,260 @@
+/*
+ * 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 static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.Locale;
+
+import org.apache.freemarker.core.templateresolver.ConditionalTemplateConfigurationFactory;
+import org.apache.freemarker.core.templateresolver.FileNameGlobMatcher;
+import org.apache.freemarker.core.templateresolver.FirstMatchTemplateConfigurationFactory;
+import org.apache.freemarker.core.templateresolver.MergingTemplateConfigurationFactory;
+import org.apache.freemarker.core.templateresolver.impl.ByteArrayTemplateLoader;
+import org.apache.freemarker.core.templateresolver.impl.StringTemplateLoader;
+import org.junit.Test;
+
+public class TemplateConfigurationWithDefaltTemplateResolverTest {
+
+    private static final String TEXT_WITH_ACCENTS = "pr\u00F3ba";
+
+    private static final CustomAttribute CUST_ATT_1 = new CustomAttribute(CustomAttribute.SCOPE_TEMPLATE);
+    private static final CustomAttribute CUST_ATT_2 = new CustomAttribute(CustomAttribute.SCOPE_TEMPLATE);
+
+    @Test
+    public void testEncoding() throws Exception {
+        Configuration cfg = createCommonEncodingTesterConfig();
+        
+        {
+            Template t = cfg.getTemplate("utf8.ftl");
+            assertEquals("utf-8", t.getEncoding());
+            assertEquals(TEXT_WITH_ACCENTS, getTemplateOutput(t));
+        }
+        {
+            Template t = cfg.getTemplate("utf16.ftl");
+            assertEquals("utf-16", t.getEncoding());
+            assertEquals(TEXT_WITH_ACCENTS, getTemplateOutput(t));
+        }
+        {
+            Template t = cfg.getTemplate("default.ftl");
+            assertEquals("iso-8859-1", t.getEncoding());
+            assertEquals(TEXT_WITH_ACCENTS, getTemplateOutput(t));
+        }
+        {
+            Template t = cfg.getTemplate("utf8-latin2.ftl");
+            assertEquals("iso-8859-2", t.getEncoding());
+            assertEquals(TEXT_WITH_ACCENTS, getTemplateOutput(t));
+        }
+        {
+            Template t = cfg.getTemplate("default-latin2.ftl");
+            assertEquals("iso-8859-2", t.getEncoding());
+            assertEquals(TEXT_WITH_ACCENTS, getTemplateOutput(t));
+        }
+    }
+    
+    @Test
+    public void testIncludeAndEncoding() throws Exception {
+        Configuration cfg = createCommonEncodingTesterConfig();
+        ByteArrayTemplateLoader tl = (ByteArrayTemplateLoader) cfg.getTemplateLoader();
+        tl.putTemplate("main.ftl", (
+                        "<#include 'utf8.ftl'>"
+                        + "<#include 'utf16.ftl'>"
+                        + "<#include 'default.ftl'>"
+                        + "<#include 'utf8-latin2.ftl'>"
+                ).getBytes("iso-8859-1"));
+        assertEquals(
+                TEXT_WITH_ACCENTS + TEXT_WITH_ACCENTS + TEXT_WITH_ACCENTS + TEXT_WITH_ACCENTS,
+                getTemplateOutput(cfg.getTemplate("main.ftl")));
+    }
+
+    @Test
+    public void testLocale() throws Exception {
+        Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
+        cfg.setLocale(Locale.US);
+        
+        StringTemplateLoader tl = new StringTemplateLoader();
+        tl.putTemplate("(de).ftl", "${.locale}");
+        tl.putTemplate("default.ftl", "${.locale}");
+        tl.putTemplate("(de)-fr.ftl",
+                ("<#ftl locale='fr_FR'>${.locale}"));
+        tl.putTemplate("default-fr.ftl",
+                ("<#ftl locale='fr_FR'>${.locale}"));
+        cfg.setTemplateLoader(tl);
+
+        TemplateConfiguration tcDe = new TemplateConfiguration();
+        tcDe.setLocale(Locale.GERMANY);
+        cfg.setTemplateConfigurations(
+                new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*(de)*"), tcDe));
+        
+        {
+            Template t = cfg.getTemplate("(de).ftl");
+            assertEquals(Locale.GERMANY, t.getLocale());
+            assertEquals("de_DE", getTemplateOutput(t));
+        }
+        {
+            Template t = cfg.getTemplate("(de).ftl", Locale.ITALY);
+            assertEquals(Locale.GERMANY, t.getLocale());
+            assertEquals("de_DE", getTemplateOutput(t));
+        }
+        {
+            Template t = cfg.getTemplate("default.ftl");
+            assertEquals(Locale.US, t.getLocale());
+            assertEquals("en_US", getTemplateOutput(t));
+        }
+        {
+            Template t = cfg.getTemplate("default.ftl", Locale.ITALY);
+            assertEquals(Locale.ITALY, t.getLocale());
+            assertEquals("it_IT", getTemplateOutput(t));
+        }
+    }
+
+    @Test
+    public void testConfigurableSettings() throws Exception {
+        Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
+        cfg.setLocale(Locale.US);
+        
+        TemplateConfiguration tcFR = new TemplateConfiguration();
+        tcFR.setLocale(Locale.FRANCE);
+        TemplateConfiguration tcYN = new TemplateConfiguration();
+        tcYN.setBooleanFormat("Y,N");
+        TemplateConfiguration tc00 = new TemplateConfiguration();
+        tc00.setNumberFormat("0.00");
+        cfg.setTemplateConfigurations(
+                new MergingTemplateConfigurationFactory(
+                        new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*(fr)*"), tcFR),
+                        new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*(yn)*"), tcYN),
+                        new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*(00)*"), tc00)
+                )
+        );
+        
+        String commonFTL = "${.locale} ${true?string} ${1.2}";
+        StringTemplateLoader tl = new StringTemplateLoader();
+        tl.putTemplate("default", commonFTL);
+        tl.putTemplate("(fr)", commonFTL);
+        tl.putTemplate("(yn)(00)", commonFTL);
+        tl.putTemplate("(00)(fr)", commonFTL);
+        cfg.setTemplateLoader(tl);
+        
+        assertEquals("en_US true 1.2", getTemplateOutput(cfg.getTemplate("default")));
+        assertEquals("fr_FR true 1,2", getTemplateOutput(cfg.getTemplate("(fr)")));
+        assertEquals("en_US Y 1.20", getTemplateOutput(cfg.getTemplate("(yn)(00)")));
+        assertEquals("fr_FR true 1,20", getTemplateOutput(cfg.getTemplate("(00)(fr)")));
+    }
+    
+    @Test
+    public void testCustomAttributes() throws Exception {
+        Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
+        
+        TemplateConfiguration tc1 = new TemplateConfiguration();
+        tc1.setCustomAttribute("a1", "a1tc1");
+        tc1.setCustomAttribute("a2", "a2tc1");
+        tc1.setCustomAttribute("a3", "a3tc1");
+        CUST_ATT_1.set("ca1tc1", tc1);
+        CUST_ATT_2.set("ca2tc1", tc1);
+        
+        TemplateConfiguration tc2 = new TemplateConfiguration();
+        tc2.setCustomAttribute("a1", "a1tc2");
+        CUST_ATT_1.set("ca1tc2", tc2);
+        
+        cfg.setTemplateConfigurations(
+                new MergingTemplateConfigurationFactory(
+                        new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*(tc1)*"), tc1),
+                        new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*(tc2)*"), tc2)
+                )
+        );
+        
+        String commonFTL = "<#ftl attributes={ 'a3': 'a3temp' }>";
+        StringTemplateLoader tl = new StringTemplateLoader();
+        tl.putTemplate("(tc1)", commonFTL);
+        tl.putTemplate("(tc1)noHeader", "");
+        tl.putTemplate("(tc2)", commonFTL);
+        tl.putTemplate("(tc1)(tc2)", commonFTL);
+        cfg.setTemplateLoader(tl);
+
+        {
+            Template t = cfg.getTemplate("(tc1)");
+            assertEquals("a1tc1", t.getCustomAttribute("a1"));
+            assertEquals("a2tc1", t.getCustomAttribute("a2"));
+            assertEquals("a3temp", t.getCustomAttribute("a3"));
+            assertEquals("ca1tc1", CUST_ATT_1.get(t));
+            assertEquals("ca2tc1", CUST_ATT_2.get(t));
+        }
+        {
+            Template t = cfg.getTemplate("(tc1)noHeader");
+            assertEquals("a1tc1", t.getCustomAttribute("a1"));
+            assertEquals("a2tc1", t.getCustomAttribute("a2"));
+            assertEquals("a3tc1", t.getCustomAttribute("a3"));
+            assertEquals("ca1tc1", CUST_ATT_1.get(t));
+            assertEquals("ca2tc1", CUST_ATT_2.get(t));
+        }
+        {
+            Template t = cfg.getTemplate("(tc2)");
+            assertEquals("a1tc2", t.getCustomAttribute("a1"));
+            assertNull(t.getCustomAttribute("a2"));
+            assertEquals("a3temp", t.getCustomAttribute("a3"));
+            assertEquals("ca1tc2", CUST_ATT_1.get(t));
+            assertNull(CUST_ATT_2.get(t));
+        }
+        {
+            Template t = cfg.getTemplate("(tc1)(tc2)");
+            assertEquals("a1tc2", t.getCustomAttribute("a1"));
+            assertEquals("a2tc1", t.getCustomAttribute("a2"));
+            assertEquals("a3temp", t.getCustomAttribute("a3"));
+            assertEquals("ca1tc2", CUST_ATT_1.get(t));
+            assertEquals("ca2tc1", CUST_ATT_2.get(t));
+        }
+    }
+    
+    private String getTemplateOutput(Template t) throws TemplateException, IOException {
+        StringWriter sw = new StringWriter();
+        t.process(null, sw);
+        return sw.toString();
+    }
+
+    private Configuration createCommonEncodingTesterConfig() throws UnsupportedEncodingException {
+        Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
+        cfg.setDefaultEncoding("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-latin2.ftl",
+                ("<#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"));
+        cfg.setTemplateLoader(tl);
+        
+        TemplateConfiguration tcUtf8 = new TemplateConfiguration();
+        tcUtf8.setEncoding("utf-8");
+        TemplateConfiguration tcUtf16 = new TemplateConfiguration();
+        tcUtf16.setEncoding("utf-16");
+        cfg.setTemplateConfigurations(
+                new FirstMatchTemplateConfigurationFactory(
+                        new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*utf8*"), tcUtf8),
+                        new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*utf16*"), tcUtf16)
+                ).allowNoMatch(true));
+        return cfg;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/src/test/java/org/apache/freemarker/core/TemplateConfigurationWithTemplateResolverTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/core/TemplateConfigurationWithTemplateResolverTest.java b/src/test/java/org/apache/freemarker/core/TemplateConfigurationWithTemplateResolverTest.java
deleted file mode 100644
index ea4ace1..0000000
--- a/src/test/java/org/apache/freemarker/core/TemplateConfigurationWithTemplateResolverTest.java
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * 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 static org.junit.Assert.*;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.UnsupportedEncodingException;
-import java.util.Locale;
-
-import org.apache.freemarker.core.templateresolver.ConditionalTemplateConfigurationFactory;
-import org.apache.freemarker.core.templateresolver.FileNameGlobMatcher;
-import org.apache.freemarker.core.templateresolver.FirstMatchTemplateConfigurationFactory;
-import org.apache.freemarker.core.templateresolver.MergingTemplateConfigurationFactory;
-import org.apache.freemarker.core.templateresolver.impl.ByteArrayTemplateLoader;
-import org.apache.freemarker.core.templateresolver.impl.StringTemplateLoader;
-import org.junit.Test;
-
-public class TemplateConfigurationWithTemplateResolverTest {
-
-    private static final String TEXT_WITH_ACCENTS = "pr\u00F3ba";
-
-    private static final CustomAttribute CUST_ATT_1 = new CustomAttribute(CustomAttribute.SCOPE_TEMPLATE);
-    private static final CustomAttribute CUST_ATT_2 = new CustomAttribute(CustomAttribute.SCOPE_TEMPLATE);
-
-    @Test
-    public void testEncoding() throws Exception {
-        Configuration cfg = createCommonEncodingTesterConfig();
-        
-        {
-            Template t = cfg.getTemplate("utf8.ftl");
-            assertEquals("utf-8", t.getEncoding());
-            assertEquals(TEXT_WITH_ACCENTS, getTemplateOutput(t));
-        }
-        {
-            Template t = cfg.getTemplate("utf8.ftl", "iso-8859-1");
-            assertEquals("utf-8", t.getEncoding());
-            assertEquals(TEXT_WITH_ACCENTS, getTemplateOutput(t));
-        }
-        {
-            Template t = cfg.getTemplate("utf16.ftl");
-            assertEquals("utf-16", t.getEncoding());
-            assertEquals(TEXT_WITH_ACCENTS, getTemplateOutput(t));
-        }
-        {
-            Template t = cfg.getTemplate("default.ftl");
-            assertEquals("iso-8859-1", t.getEncoding());
-            assertEquals(TEXT_WITH_ACCENTS, getTemplateOutput(t));
-        }
-        {
-            Template t = cfg.getTemplate("default.ftl", "iso-8859-5");
-            assertEquals("iso-8859-5", t.getEncoding());
-            assertEquals(new String(TEXT_WITH_ACCENTS.getBytes("iso-8859-1"), "iso-8859-5"),
-                    getTemplateOutput(t));
-        }
-        {
-            Template t = cfg.getTemplate("utf8-latin2.ftl");
-            assertEquals("iso-8859-2", t.getEncoding());
-            assertEquals(TEXT_WITH_ACCENTS, getTemplateOutput(t));
-        }
-        {
-            Template t = cfg.getTemplate("default-latin2.ftl");
-            assertEquals("iso-8859-2", t.getEncoding());
-            assertEquals(TEXT_WITH_ACCENTS, getTemplateOutput(t));
-        }
-    }
-    
-    @Test
-    public void testIncludeAndEncoding() throws Exception {
-        Configuration cfg = createCommonEncodingTesterConfig();
-        ByteArrayTemplateLoader tl = (ByteArrayTemplateLoader) cfg.getTemplateLoader();
-        tl.putTemplate("main.ftl", (
-                        "<#include 'utf8.ftl'>"
-                        + "<#include 'utf16.ftl'>"
-                        + "<#include 'default.ftl'>"
-                        + "<#include 'utf8-latin2.ftl'>"
-                        // With mostly ignored encoding params:
-                        + "<#include 'utf8.ftl' encoding='utf-16'>"
-                        + "<#include 'utf16.ftl' encoding='iso-8859-5'>"
-                        + "<#include 'default.ftl' encoding='iso-8859-5'>"
-                        + "<#include 'utf8-latin2.ftl' encoding='iso-8859-5'>"
-                ).getBytes("iso-8859-1"));
-        assertEquals(
-                TEXT_WITH_ACCENTS + TEXT_WITH_ACCENTS + TEXT_WITH_ACCENTS + TEXT_WITH_ACCENTS
-                + TEXT_WITH_ACCENTS + TEXT_WITH_ACCENTS
-                + new String(TEXT_WITH_ACCENTS.getBytes("iso-8859-1"), "iso-8859-5")
-                + TEXT_WITH_ACCENTS,
-                getTemplateOutput(cfg.getTemplate("main.ftl")));
-    }
-
-    @Test
-    public void testLocale() throws Exception {
-        Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
-        cfg.setLocale(Locale.US);
-        
-        StringTemplateLoader tl = new StringTemplateLoader();
-        tl.putTemplate("(de).ftl", "${.locale}");
-        tl.putTemplate("default.ftl", "${.locale}");
-        tl.putTemplate("(de)-fr.ftl",
-                ("<#ftl locale='fr_FR'>${.locale}"));
-        tl.putTemplate("default-fr.ftl",
-                ("<#ftl locale='fr_FR'>${.locale}"));
-        cfg.setTemplateLoader(tl);
-
-        TemplateConfiguration tcDe = new TemplateConfiguration();
-        tcDe.setLocale(Locale.GERMANY);
-        cfg.setTemplateConfigurations(new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*(de)*"), tcDe));
-        
-        {
-            Template t = cfg.getTemplate("(de).ftl");
-            assertEquals(Locale.GERMANY, t.getLocale());
-            assertEquals("de_DE", getTemplateOutput(t));
-        }
-        {
-            Template t = cfg.getTemplate("(de).ftl", Locale.ITALY);
-            assertEquals(Locale.GERMANY, t.getLocale());
-            assertEquals("de_DE", getTemplateOutput(t));
-        }
-        {
-            Template t = cfg.getTemplate("default.ftl");
-            assertEquals(Locale.US, t.getLocale());
-            assertEquals("en_US", getTemplateOutput(t));
-        }
-        {
-            Template t = cfg.getTemplate("default.ftl", Locale.ITALY);
-            assertEquals(Locale.ITALY, t.getLocale());
-            assertEquals("it_IT", getTemplateOutput(t));
-        }
-    }
-
-    @Test
-    public void testPlainText() throws Exception {
-        Configuration cfg = createCommonEncodingTesterConfig();
-        cfg.setIncompatibleImprovements(Configuration.VERSION_3_0_0);
-        
-        TemplateConfiguration tcDE = new TemplateConfiguration();
-        tcDE.setLocale(Locale.GERMANY);
-        TemplateConfiguration tcYN = new TemplateConfiguration();
-        tcYN.setBooleanFormat("Y,N");
-        cfg.setTemplateConfigurations(
-                    new MergingTemplateConfigurationFactory(
-                            cfg.getTemplateConfigurations(),
-                            new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("utf16.ftl"), tcDE),
-                            new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("utf16.ftl"), tcYN)
-                    )
-                );
-        
-        {
-            Template t = cfg.getTemplate("utf8.ftl", null, null, false);
-            assertEquals("utf-8", t.getEncoding());
-            assertEquals(TEXT_WITH_ACCENTS, getTemplateOutput(t));
-            assertEquals(Locale.US, t.getLocale());
-            assertEquals("true,false", t.getBooleanFormat());
-        }
-        {
-            Template t = cfg.getTemplate("utf8.ftl", null, "iso-8859-1", false);
-            assertEquals("utf-8", t.getEncoding());
-            assertEquals(TEXT_WITH_ACCENTS, getTemplateOutput(t));
-        }
-        {
-            Template t = cfg.getTemplate("utf16.ftl", null, null, false);
-            assertEquals("utf-16", t.getEncoding());
-            assertEquals(TEXT_WITH_ACCENTS, getTemplateOutput(t));
-            assertEquals(Locale.GERMANY, t.getLocale());
-            assertEquals("Y,N", t.getBooleanFormat());
-        }
-        {
-            Template t = cfg.getTemplate("default.ftl", null, null, false);
-            assertEquals("iso-8859-1", t.getEncoding());
-            assertEquals(TEXT_WITH_ACCENTS, getTemplateOutput(t));
-        }
-    }
-
-    @Test
-    public void testConfigurableSettings() throws Exception {
-        Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
-        cfg.setLocale(Locale.US);
-        
-        TemplateConfiguration tcFR = new TemplateConfiguration();
-        tcFR.setLocale(Locale.FRANCE);
-        TemplateConfiguration tcYN = new TemplateConfiguration();
-        tcYN.setBooleanFormat("Y,N");
-        TemplateConfiguration tc00 = new TemplateConfiguration();
-        tc00.setNumberFormat("0.00");
-        cfg.setTemplateConfigurations(
-                new MergingTemplateConfigurationFactory(
-                        new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*(fr)*"), tcFR),
-                        new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*(yn)*"), tcYN),
-                        new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*(00)*"), tc00)
-                )
-        );
-        
-        String commonFTL = "${.locale} ${true?string} ${1.2}";
-        StringTemplateLoader tl = new StringTemplateLoader();
-        tl.putTemplate("default", commonFTL);
-        tl.putTemplate("(fr)", commonFTL);
-        tl.putTemplate("(yn)(00)", commonFTL);
-        tl.putTemplate("(00)(fr)", commonFTL);
-        cfg.setTemplateLoader(tl);
-        
-        assertEquals("en_US true 1.2", getTemplateOutput(cfg.getTemplate("default")));
-        assertEquals("fr_FR true 1,2", getTemplateOutput(cfg.getTemplate("(fr)")));
-        assertEquals("en_US Y 1.20", getTemplateOutput(cfg.getTemplate("(yn)(00)")));
-        assertEquals("fr_FR true 1,20", getTemplateOutput(cfg.getTemplate("(00)(fr)")));
-    }
-    
-    @Test
-    public void testCustomAttributes() throws Exception {
-        Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
-        
-        TemplateConfiguration tc1 = new TemplateConfiguration();
-        tc1.setCustomAttribute("a1", "a1tc1");
-        tc1.setCustomAttribute("a2", "a2tc1");
-        tc1.setCustomAttribute("a3", "a3tc1");
-        CUST_ATT_1.set("ca1tc1", tc1);
-        CUST_ATT_2.set("ca2tc1", tc1);
-        
-        TemplateConfiguration tc2 = new TemplateConfiguration();
-        tc2.setCustomAttribute("a1", "a1tc2");
-        CUST_ATT_1.set("ca1tc2", tc2);
-        
-        cfg.setTemplateConfigurations(
-                new MergingTemplateConfigurationFactory(
-                        new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*(tc1)*"), tc1),
-                        new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*(tc2)*"), tc2)
-                )
-        );
-        
-        String commonFTL = "<#ftl attributes={ 'a3': 'a3temp' }>";
-        StringTemplateLoader tl = new StringTemplateLoader();
-        tl.putTemplate("(tc1)", commonFTL);
-        tl.putTemplate("(tc1)noHeader", "");
-        tl.putTemplate("(tc2)", commonFTL);
-        tl.putTemplate("(tc1)(tc2)", commonFTL);
-        cfg.setTemplateLoader(tl);
-
-        {
-            Template t = cfg.getTemplate("(tc1)");
-            assertEquals("a1tc1", t.getCustomAttribute("a1"));
-            assertEquals("a2tc1", t.getCustomAttribute("a2"));
-            assertEquals("a3temp", t.getCustomAttribute("a3"));
-            assertEquals("ca1tc1", CUST_ATT_1.get(t));
-            assertEquals("ca2tc1", CUST_ATT_2.get(t));
-        }
-        {
-            Template t = cfg.getTemplate("(tc1)noHeader");
-            assertEquals("a1tc1", t.getCustomAttribute("a1"));
-            assertEquals("a2tc1", t.getCustomAttribute("a2"));
-            assertEquals("a3tc1", t.getCustomAttribute("a3"));
-            assertEquals("ca1tc1", CUST_ATT_1.get(t));
-            assertEquals("ca2tc1", CUST_ATT_2.get(t));
-        }
-        {
-            Template t = cfg.getTemplate("(tc2)");
-            assertEquals("a1tc2", t.getCustomAttribute("a1"));
-            assertNull(t.getCustomAttribute("a2"));
-            assertEquals("a3temp", t.getCustomAttribute("a3"));
-            assertEquals("ca1tc2", CUST_ATT_1.get(t));
-            assertNull(CUST_ATT_2.get(t));
-        }
-        {
-            Template t = cfg.getTemplate("(tc1)(tc2)");
-            assertEquals("a1tc2", t.getCustomAttribute("a1"));
-            assertEquals("a2tc1", t.getCustomAttribute("a2"));
-            assertEquals("a3temp", t.getCustomAttribute("a3"));
-            assertEquals("ca1tc2", CUST_ATT_1.get(t));
-            assertEquals("ca2tc1", CUST_ATT_2.get(t));
-        }
-    }
-    
-    private String getTemplateOutput(Template t) throws TemplateException, IOException {
-        StringWriter sw = new StringWriter();
-        t.process(null, sw);
-        return sw.toString();
-    }
-
-    private Configuration createCommonEncodingTesterConfig() throws UnsupportedEncodingException {
-        Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
-        cfg.setDefaultEncoding("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-latin2.ftl",
-                ("<#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"));
-        cfg.setTemplateLoader(tl);
-        
-        TemplateConfiguration tcUtf8 = new TemplateConfiguration();
-        tcUtf8.setEncoding("utf-8");
-        TemplateConfiguration tcUtf16 = new TemplateConfiguration();
-        tcUtf16.setEncoding("utf-16");
-        cfg.setTemplateConfigurations(
-                new FirstMatchTemplateConfigurationFactory(
-                        new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*utf8*"), tcUtf8),
-                        new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*utf16*"), tcUtf16)
-                ).allowNoMatch(true));
-        return cfg;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/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
new file mode 100644
index 0000000..c387d36
--- /dev/null
+++ b/src/test/java/org/apache/freemarker/core/TemplateGetEncodingTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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 static org.junit.Assert.*;
+
+import java.io.IOException;
+
+import org.apache.freemarker.core.templateresolver.ConditionalTemplateConfigurationFactory;
+import org.apache.freemarker.core.templateresolver.FileNameGlobMatcher;
+import org.apache.freemarker.core.templateresolver.impl.StrongCacheStorage;
+import org.apache.freemarker.test.MonitoredTemplateLoader;
+import org.junit.Test;
+
+public class TemplateGetEncodingTest {
+
+    @Test
+    public void test() throws IOException {
+        Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
+        {
+            cfg.setDefaultEncoding("ISO-8859-2");
+            MonitoredTemplateLoader tl = new MonitoredTemplateLoader();
+            tl.putBinaryTemplate("bin", "test");
+            tl.putBinaryTemplate("bin-static", "<#test>");
+            tl.putTextTemplate("text", "test");
+            tl.putTextTemplate("text-static", "<#test>");
+            TemplateConfiguration staticTextTC = new TemplateConfiguration();
+            staticTextTC.setTemplateLanguage(TemplateLanguage.STATIC_TEXT);
+            cfg.setTemplateConfigurations(
+                    new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*-static*"), staticTextTC));
+            cfg.setTemplateLoader(tl);
+            cfg.setCacheStorage(new StrongCacheStorage());
+        }
+
+        assertEquals("ISO-8859-2", cfg.getTemplate("bin").getEncoding());
+        assertEquals("ISO-8859-2", cfg.getTemplate("bin-static").getEncoding());
+        assertNull(cfg.getTemplate("text").getEncoding());
+        assertNull(cfg.getTemplate("text-static").getEncoding());
+        assertNull(new Template(null, "test", cfg).getEncoding());
+        assertNull(Template.createPlainTextTemplate(null, "<#test>", cfg).getEncoding());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/src/test/java/org/apache/freemarker/core/TemplateLookupStrategyTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/core/TemplateLookupStrategyTest.java b/src/test/java/org/apache/freemarker/core/TemplateLookupStrategyTest.java
index e991df8..062d8e1 100644
--- a/src/test/java/org/apache/freemarker/core/TemplateLookupStrategyTest.java
+++ b/src/test/java/org/apache/freemarker/core/TemplateLookupStrategyTest.java
@@ -22,6 +22,7 @@ package org.apache.freemarker.core;
 import static org.junit.Assert.*;
 
 import java.io.IOException;
+import java.io.Serializable;
 import java.io.StringWriter;
 import java.util.Locale;
 
@@ -295,7 +296,7 @@ public class TemplateLookupStrategyTest {
             cfg.clearTemplateCache();
         }
     }
-    
+
     @Test
     public void testCustomLookupCondition() throws IOException, TemplateException {
         Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
@@ -331,8 +332,8 @@ public class TemplateLookupStrategyTest {
         
         {
             final Locale locale = new Locale("xx");
-            final String domain = "foo.com";
-            final Template t = cfg.getTemplate("t.ftl", locale, domain, "utf-8", false);
+            final Domain domain = new Domain("foo.com");
+            final Template t = cfg.getTemplate("t.ftl", locale, domain);
             assertEquals("t.ftl", t.getName());
             assertEquals("@foo.com/t.ftl", t.getSourceName());
             assertEquals(locale, t.getLocale());
@@ -354,8 +355,8 @@ public class TemplateLookupStrategyTest {
 
         {
             final Locale locale = new Locale("xx");
-            final String domain = "bar.com";
-            final Template t = cfg.getTemplate("t.ftl", locale, domain, "utf-8", false);
+            final Domain domain = new Domain("bar.com");
+            final Template t = cfg.getTemplate("t.ftl", locale, domain);
             assertEquals("t.ftl", t.getName());
             assertEquals("@bar.com/t.ftl", t.getSourceName());
             assertEquals(locale, t.getLocale());
@@ -379,8 +380,8 @@ public class TemplateLookupStrategyTest {
         
         {
             final Locale locale = new Locale("xx", "YY");
-            final String domain = "baaz.com";
-            final Template t = cfg.getTemplate("t.ftl", locale, domain, "utf-8", false);
+            final Domain domain = new Domain("baaz.com");
+            final Template t = cfg.getTemplate("t.ftl", locale, domain);
             assertEquals("t.ftl", t.getName());
             assertEquals("@default/t.ftl", t.getSourceName());
             assertEquals(locale, t.getLocale());
@@ -404,8 +405,8 @@ public class TemplateLookupStrategyTest {
         
         {
             final Locale locale = new Locale("xx", "YY");
-            final String domain = "nosuch.com";
-            final Template t = cfg.getTemplate("i.ftl", locale, domain, "utf-8", false);
+            final Domain domain = new Domain("nosuch.com");
+            final Template t = cfg.getTemplate("i.ftl", locale, domain);
             assertEquals("i.ftl", t.getName());
             assertEquals("@default/i_xx.ftl", t.getSourceName());
             assertEquals(locale, t.getLocale());
@@ -424,8 +425,8 @@ public class TemplateLookupStrategyTest {
         {
             cfg.setLocalizedLookup(false);
             final Locale locale = new Locale("xx", "YY");
-            final String domain = "nosuch.com";
-            final Template t = cfg.getTemplate("i.ftl", locale, domain, "utf-8", false);
+            final Domain domain = new Domain("nosuch.com");
+            final Template t = cfg.getTemplate("i.ftl", locale, domain);
             assertEquals("i.ftl", t.getName());
             assertEquals("@default/i.ftl", t.getSourceName());
             assertEquals(locale, t.getLocale());
@@ -442,8 +443,8 @@ public class TemplateLookupStrategyTest {
         
         {
             final Locale locale = new Locale("xx");
-            final String domain = "foo.com";
-            final Template t = cfg.getTemplate("t2.ftl", locale, domain, "utf-8", false);
+            final Domain domain = new Domain("foo.com");
+            final Template t = cfg.getTemplate("t2.ftl", locale, domain);
             assertOutputEquals(t2XxLocaleExpectedOutput, t);
             assertEquals(
                     ImmutableList.of(
@@ -458,8 +459,8 @@ public class TemplateLookupStrategyTest {
         
         {
             final Locale locale = new Locale("yy");
-            final String domain = "foo.com";
-            final Template t = cfg.getTemplate("t2.ftl", locale, domain, "utf-8", false);
+            final Domain domain = new Domain("foo.com");
+            final Template t = cfg.getTemplate("t2.ftl", locale, domain);
             assertOutputEquals(t2OtherLocaleExpectedOutput, t);
             assertEquals(
                     ImmutableList.of(
@@ -475,8 +476,8 @@ public class TemplateLookupStrategyTest {
         {
             cfg.setLocalizedLookup(false);
             final Locale locale = new Locale("xx");
-            final String domain = "foo.com";
-            final Template t = cfg.getTemplate("t2.ftl", locale, domain, "utf-8", false);
+            final Domain domain = new Domain("foo.com");
+            final Template t = cfg.getTemplate("t2.ftl", locale, domain);
             assertOutputEquals(t2OtherLocaleExpectedOutput, t);
             assertEquals(
                     ImmutableList.of(
@@ -492,8 +493,8 @@ public class TemplateLookupStrategyTest {
         
         {
             final Locale locale = new Locale("xx");
-            final String domain = "foo.com";
-            cfg.getTemplate("i3.ftl", locale, domain, "utf-8", false);
+            final Domain domain = new Domain("foo.com");
+            cfg.getTemplate("i3.ftl", locale, domain);
             assertEquals(
                     ImmutableList.of("@foo.com/i3_xx.ftl"),
                     tl.getLoadNames());
@@ -504,9 +505,9 @@ public class TemplateLookupStrategyTest {
         
         {
             final Locale locale = new Locale("xx");
-            final String domain = "bar.com";
+            final Domain domain = new Domain("bar.com");
             try {
-                cfg.getTemplate("i3.ftl", locale, domain, "utf-8", false);
+                cfg.getTemplate("i3.ftl", locale, domain);
             } catch (TemplateNotFoundException e) {
                 assertEquals("i3.ftl", e.getTemplateName());
                 assertEquals(domain, e.getCustomLookupCondition());
@@ -522,6 +523,29 @@ public class TemplateLookupStrategyTest {
         }
         
     }
+
+    public static class Domain implements Serializable {
+        private final String name;
+
+        public Domain(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            Domain domain = (Domain) o;
+
+            return name != null ? name.equals(domain.name) : domain.name == null;
+        }
+
+        @Override
+        public int hashCode() {
+            return name != null ? name.hashCode() : 0;
+        }
+    }
     
     @Test
     public void testNonparsed() throws IOException {
@@ -594,9 +618,9 @@ public class TemplateLookupStrategyTest {
         private MyTemplateLookupStrategy() { }
 
         @Override
-        public TemplateLookupResult lookup(TemplateLookupContext ctx) throws IOException {
+        public <R extends TemplateLookupResult> R lookup(TemplateLookupContext<R> ctx) throws IOException {
             String lang = ctx.getTemplateLocale().getLanguage().toLowerCase();
-            TemplateLookupResult lookupResult = ctx.lookupWithAcquisitionStrategy(lang + "/" + ctx.getTemplateName());
+            R lookupResult = ctx.lookupWithAcquisitionStrategy(lang + "/" + ctx.getTemplateName());
             if (lookupResult.isPositive()) {
                 return lookupResult;
             }
@@ -611,8 +635,8 @@ public class TemplateLookupStrategyTest {
         public static final DomainTemplateLookupStrategy INSTANCE = new DomainTemplateLookupStrategy();
 
         @Override
-        public TemplateLookupResult lookup(TemplateLookupContext ctx) throws IOException {
-            String domain = (String) ctx.getCustomLookupCondition();
+        public <R extends TemplateLookupResult> R lookup(TemplateLookupContext<R> ctx) throws IOException {
+            Domain domain = (Domain) ctx.getCustomLookupCondition();
             if (domain == null) {
                 throw new NullPointerException("The domain wasn't specified");
             }
@@ -624,8 +648,8 @@ public class TemplateLookupStrategyTest {
                 return ctx.createNegativeLookupResult();
             }
             
-            TemplateLookupResult lookupResult = ctx.lookupWithLocalizedThenAcquisitionStrategy(
-                    "@" + domain + "/" + templateName,
+            R lookupResult = ctx.lookupWithLocalizedThenAcquisitionStrategy(
+                    "@" + domain.name + "/" + templateName,
                     ctx.getTemplateLocale());
             if (lookupResult.isPositive()) {
                 return lookupResult;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/src/test/java/org/apache/freemarker/core/TemplateNotFoundMessageTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/core/TemplateNotFoundMessageTest.java b/src/test/java/org/apache/freemarker/core/TemplateNotFoundMessageTest.java
index 6758771..7348a69 100644
--- a/src/test/java/org/apache/freemarker/core/TemplateNotFoundMessageTest.java
+++ b/src/test/java/org/apache/freemarker/core/TemplateNotFoundMessageTest.java
@@ -25,6 +25,7 @@ import static org.junit.Assert.*;
 
 import java.io.File;
 import java.io.IOException;
+import java.io.Serializable;
 
 import org.apache.freemarker.core.templateresolver.MalformedTemplateNameException;
 import org.apache.freemarker.core.templateresolver.TemplateLoader;
@@ -161,7 +162,12 @@ public class TemplateNotFoundMessageTest {
         }
         
         try {
-            cfg.getTemplate("./missing", null, "example.com", null, false);
+            cfg.getTemplate("./missing", null, new Serializable() {
+                @Override
+                public String toString() {
+                    return "example.com";
+                }
+            });
             fail();
         } catch (TemplateNotFoundException e) {
             showErrorMessage(e.getMessage());

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/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 ab27c2a..996f4fd 100644
--- a/src/test/java/org/apache/freemarker/core/templateresolver/DefaultTemplateResolverTest.java
+++ b/src/test/java/org/apache/freemarker/core/templateresolver/DefaultTemplateResolverTest.java
@@ -23,7 +23,6 @@ import static org.junit.Assert.*;
 
 import java.io.IOException;
 import java.io.Serializable;
-import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import java.util.Locale;
 
@@ -55,13 +54,13 @@ public class DefaultTemplateResolverTest {
         tr.setTemplateUpdateDelayMilliseconds(1000L);
         loader.setThrowException(true);
         try {
-            tr.getTemplate("t", Locale.getDefault(), null, "").getTemplate();
+            tr.getTemplate("t", Locale.getDefault(), null).getTemplate();
             fail();
         } catch (IOException e) {
             assertEquals("mock IO exception", e.getMessage());
             assertEquals(1, loader.getLoadAttemptCount());
             try {
-                tr.getTemplate("t", Locale.getDefault(), null, "").getTemplate();
+                tr.getTemplate("t", Locale.getDefault(), null).getTemplate();
                 fail();
             } catch (IOException e2) {
                 // Still 1 - returned cached exception
@@ -72,7 +71,7 @@ public class DefaultTemplateResolverTest {
                 assertEquals(1, loader.getLoadAttemptCount());
                 try {
                     Thread.sleep(1100L);
-                    tr.getTemplate("t", Locale.getDefault(), null, "").getTemplate();
+                    tr.getTemplate("t", Locale.getDefault(), null).getTemplate();
                     fail();
                 } catch (IOException e3) {
                     // Cache had to retest
@@ -91,13 +90,13 @@ public class DefaultTemplateResolverTest {
                 DefaultTemplateNameFormat.INSTANCE, new Configuration());
         cache.setTemplateUpdateDelayMilliseconds(1000L);
         cache.setLocalizedLookup(false);
-        assertNull(cache.getTemplate("t", Locale.getDefault(), null, "").getTemplate());
+        assertNull(cache.getTemplate("t", Locale.getDefault(), null).getTemplate());
         assertEquals(1, loader.getLoadAttemptCount());
-        assertNull(cache.getTemplate("t", Locale.getDefault(), null, "").getTemplate());
+        assertNull(cache.getTemplate("t", Locale.getDefault(), null).getTemplate());
         // Still 1 - returned cached exception
         assertEquals(1, loader.getLoadAttemptCount());
         Thread.sleep(1100L);
-        assertNull(cache.getTemplate("t", Locale.getDefault(), null, "").getTemplate());
+        assertNull(cache.getTemplate("t", Locale.getDefault(), null).getTemplate());
         // Cache had to retest
         assertEquals(2, loader.getLoadAttemptCount());
     }
@@ -274,6 +273,7 @@ public class DefaultTemplateResolverTest {
     public void testWrongEncodingReload() throws IOException {
         Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
         cfg.setLocale(Locale.US);
+        cfg.setDefaultEncoding("utf-8");
         
         MonitoredTemplateLoader tl = new MonitoredTemplateLoader();
         tl.putBinaryTemplate("utf-8_en.ftl", "<#ftl encoding='utf-8'>B�ka");
@@ -283,25 +283,7 @@ public class DefaultTemplateResolverTest {
         cfg.setTemplateLoader(tl);
         
         {
-            Template t = cfg.getTemplate("utf-8.ftl", "Utf-8");
-            assertEquals("utf-8.ftl", t.getName());
-            assertEquals("utf-8_en.ftl", t.getSourceName());
-            assertEquals("Utf-8", t.getEncoding());
-            assertEquals("B�ka", t.toString());
-            
-            assertEquals(
-                    ImmutableList.of(
-                            CreateSessionEvent.INSTANCE,
-                            new LoadEvent("utf-8_en_US.ftl", TemplateLoadingResultStatus.NOT_FOUND),
-                            new LoadEvent("utf-8_en.ftl", TemplateLoadingResultStatus.OPENED),
-                            CloseSessionEvent.INSTANCE),
-                    tl.getEvents());
-        }
-        
-        {
-            tl.clearEvents();
-            
-            Template t = cfg.getTemplate("utf-8.ftl", "ISO-8859-5");
+            Template t = cfg.getTemplate("utf-8.ftl");
             assertEquals("utf-8.ftl", t.getName());
             assertEquals("utf-8_en.ftl", t.getSourceName());
             assertEquals("utf-8", t.getEncoding());
@@ -315,11 +297,11 @@ public class DefaultTemplateResolverTest {
                             CloseSessionEvent.INSTANCE),
                     tl.getEvents());
         }
-        
+
         {
             tl.clearEvents();
             
-            Template t = cfg.getTemplate("iso-8859-1.ftl", "utf-8");
+            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.getEncoding());
@@ -338,6 +320,7 @@ public class DefaultTemplateResolverTest {
     public void testNoWrongEncodingForTemplateLoader2WithReader() throws IOException {
         Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
         cfg.setLocale(Locale.US);
+        cfg.setDefaultEncoding("utf-8");
         
         MonitoredTemplateLoader tl = new MonitoredTemplateLoader();
         tl.putTextTemplate("foo_en.ftl", "<#ftl encoding='utf-8'>\u0151");
@@ -345,25 +328,7 @@ public class DefaultTemplateResolverTest {
         cfg.setTemplateLoader(tl);
         
         {
-            Template t = cfg.getTemplate("foo.ftl", "Utf-8");
-            assertEquals("foo.ftl", t.getName());
-            assertEquals("foo_en.ftl", t.getSourceName());
-            assertNull(t.getEncoding());
-            assertEquals("\u0151", t.toString());
-            
-            assertEquals(
-                    ImmutableList.of(
-                            CreateSessionEvent.INSTANCE,
-                            new LoadEvent("foo_en_US.ftl", TemplateLoadingResultStatus.NOT_FOUND),
-                            new LoadEvent("foo_en.ftl", TemplateLoadingResultStatus.OPENED),
-                            CloseSessionEvent.INSTANCE),                
-                    tl.getEvents());
-        }
-        
-        {
-            tl.clearEvents();
-            
-            Template t = cfg.getTemplate("foo.ftl", "iso-8859-1");
+            Template t = cfg.getTemplate("foo.ftl");
             assertEquals("foo.ftl", t.getName());
             assertEquals("foo_en.ftl", t.getSourceName());
             assertNull(t.getEncoding());
@@ -378,89 +343,12 @@ public class DefaultTemplateResolverTest {
                     tl.getEvents());
         }
     }
-    
-    @Test
-    public void testEncodingSelection() throws IOException {
-        Locale hungary = new Locale("hu", "HU"); 
-                
-        Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
-        cfg.setDefaultEncoding("utf-8");
-        
-        MonitoredTemplateLoader tl = new MonitoredTemplateLoader();
-        tl.putBinaryTemplate("t.ftl", "Foo");
-        tl.putBinaryTemplate("t_de.ftl", "Vuu");
-        tl.putBinaryTemplate("t2.ftl", "<#ftl encoding='ISO-8859-5'>\u043f\u0440\u0438\u043c\u0435\u0440", Charset.forName("ISO-8859-5"), "v1");
-        tl.putBinaryTemplate("t2_de.ftl", "<#ftl encoding='ISO-8859-5'>\u043f\u0440\u0438\u043c\u0435\u0440", Charset.forName("ISO-8859-5"), "v1");
-        cfg.setTemplateLoader(tl);
 
-        // No locale-to-encoding mapping exists yet:
-        {
-            Template t = cfg.getTemplate("t.ftl", Locale.GERMANY);
-            assertEquals("t.ftl", t.getName());
-            assertEquals("t_de.ftl", t.getSourceName());
-            assertEquals("utf-8", t.getEncoding());
-            assertEquals("Vuu", t.toString());
-        }
-        
-        cfg.setEncoding(Locale.GERMANY, "ISO-8859-1");
-        cfg.setEncoding(hungary, "ISO-8859-2");
-        {
-            Template t = cfg.getTemplate("t.ftl", Locale.CHINESE);
-            assertEquals("t.ftl", t.getName());
-            assertEquals("t.ftl", t.getSourceName());
-            assertEquals("utf-8", t.getEncoding());
-            assertEquals("Foo", t.toString());
-        }
-        {
-            Template t = cfg.getTemplate("t.ftl", Locale.GERMANY);
-            assertEquals("t.ftl", t.getName());
-            assertEquals("t_de.ftl", t.getSourceName());
-            assertEquals("ISO-8859-1", t.getEncoding());
-            assertEquals("Vuu", t.toString());
-        }
-        {
-            Template t = cfg.getTemplate("t.ftl", hungary);
-            assertEquals("t.ftl", t.getName());
-            assertEquals("t.ftl", t.getSourceName());
-            assertEquals("ISO-8859-2", t.getEncoding());
-            assertEquals("Foo", t.toString());
-        }
-        
-        // #ftl header overrides:
-        {
-            Template t = cfg.getTemplate("t2.ftl", Locale.CHINESE);
-            assertEquals("t2.ftl", t.getName());
-            assertEquals("t2.ftl", t.getSourceName());
-            assertEquals("ISO-8859-5", t.getEncoding());
-            assertEquals("\u043f\u0440\u0438\u043c\u0435\u0440", t.toString());
-        }
-        {
-            Template t = cfg.getTemplate("t2.ftl", Locale.GERMANY);
-            assertEquals("t2.ftl", t.getName());
-            assertEquals("t2_de.ftl", t.getSourceName());
-            assertEquals("ISO-8859-5", t.getEncoding());
-            assertEquals("\u043f\u0440\u0438\u043c\u0435\u0440", t.toString());
-        }
-        {
-            Template t = cfg.getTemplate("t2.ftl", hungary);
-            assertEquals("t2.ftl", t.getName());
-            assertEquals("t2.ftl", t.getSourceName());
-            assertEquals("ISO-8859-5", t.getEncoding());
-            assertEquals("\u043f\u0440\u0438\u043c\u0435\u0440", t.toString());
-        }
-    }
-    
     @Test
     public void testTemplateNameFormatException() throws IOException {
         Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
         cfg.setTemplateNameFormat(DefaultTemplateNameFormat.INSTANCE);
         try {
-            cfg.getTemplate("../x", null, null, null, true);
-            fail();
-        } catch (MalformedTemplateNameException e) {
-            // expected
-        }
-        try {
             cfg.getTemplate("../x");
             fail();
         } catch (MalformedTemplateNameException e) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/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 eea08f2..b2f8c26 100644
--- a/src/test/java/org/apache/freemarker/test/templatesuite/TemplateTestCase.java
+++ b/src/test/java/org/apache/freemarker/test/templatesuite/TemplateTestCase.java
@@ -146,10 +146,6 @@ 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 ("clear_encoding_map".equals(param)) {
-            if (_StringUtil.getYesNo(value)) {
-                conf.clearEncodingMap();
-            }
         } else if ("input_encoding".equals(param)) {
             conf.setDefaultEncoding(value);
         // INCOMPATIBLE_IMPROVEMENTS is a list here, and was already set in the constructor.

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/src/test/resources/org/apache/freemarker/test/templatesuite/expected/include2.txt
----------------------------------------------------------------------
diff --git a/src/test/resources/org/apache/freemarker/test/templatesuite/expected/include2.txt b/src/test/resources/org/apache/freemarker/test/templatesuite/expected/include2.txt
index ad47d13..b7c43a9 100644
--- a/src/test/resources/org/apache/freemarker/test/templatesuite/expected/include2.txt
+++ b/src/test/resources/org/apache/freemarker/test/templatesuite/expected/include2.txt
@@ -19,11 +19,6 @@
 A pr�ba
 A pr�ba
 
-A próba
-A próba
-A pr�ba
-A pr�ba
-
 A pr�ba
 A pr�ba
 A pr�ba

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/src/test/resources/org/apache/freemarker/test/templatesuite/templates/charset-in-header_inc2.ftl
----------------------------------------------------------------------
diff --git a/src/test/resources/org/apache/freemarker/test/templatesuite/templates/charset-in-header_inc2.ftl b/src/test/resources/org/apache/freemarker/test/templatesuite/templates/charset-in-header_inc2.ftl
index 0b3427a..66100ec 100644
--- a/src/test/resources/org/apache/freemarker/test/templatesuite/templates/charset-in-header_inc2.ftl
+++ b/src/test/resources/org/apache/freemarker/test/templatesuite/templates/charset-in-header_inc2.ftl
@@ -16,4 +16,4 @@
   specific language governing permissions and limitations
   under the License.
 -->
-\ufffd\ufffd\ufffd\ufffd
+\u0151\u0150\u0171\u0170

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/src/test/resources/org/apache/freemarker/test/templatesuite/templates/include2-included-encoding.ftl
----------------------------------------------------------------------
diff --git a/src/test/resources/org/apache/freemarker/test/templatesuite/templates/include2-included-encoding.ftl b/src/test/resources/org/apache/freemarker/test/templatesuite/templates/include2-included-encoding.ftl
deleted file mode 100644
index 8a1a56d..0000000
--- a/src/test/resources/org/apache/freemarker/test/templatesuite/templates/include2-included-encoding.ftl
+++ /dev/null
@@ -1,20 +0,0 @@
-<#ftl encoding='utf-8'>
-<#--
-  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.
--->
-${'A'} pr�ba

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/src/test/resources/org/apache/freemarker/test/templatesuite/templates/include2.ftl
----------------------------------------------------------------------
diff --git a/src/test/resources/org/apache/freemarker/test/templatesuite/templates/include2.ftl b/src/test/resources/org/apache/freemarker/test/templatesuite/templates/include2.ftl
index 41b8ed5..5f3ccc3 100644
--- a/src/test/resources/org/apache/freemarker/test/templatesuite/templates/include2.ftl
+++ b/src/test/resources/org/apache/freemarker/test/templatesuite/templates/include2.ftl
@@ -20,12 +20,6 @@
 <#assign s = "de">
 <#include "inclu" + s + "2-included.ftl">
 
-<#assign sEncoding="ISO-8859-1">
-<#include "include2-included.ftl" encoding="ISO-8859-1">
-<#include "include2-included.ftl" encoding=sEncoding>
-<#include "include2-included-encoding.ftl" encoding="ISO-8859-1">
-<#include "include2-included-encoding.ftl" encoding=sEncoding>
-
 <#assign bTrue=true>
 <#assign bFalse=false>
 <#include "include2-included.ftl" ignore_missing=true>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/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 fdc65b1..e38110e 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,6 @@
  <!ELEMENT setting EMPTY>
      <!ATTLIST setting 
             auto_import CDATA #IMPLIED
-            clear_encoding_map (Y|N) #IMPLIED
             input_encoding CDATA #IMPLIED
             locale CDATA #IMPLIED
             object_wrapper CDATA #IMPLIED
@@ -61,9 +60,7 @@ Note that for the incompatible_improvements setting you can specify a list of ve
    <testCase name="arithmetic" />
    <testCase name="assignments" noOutput="true" />
    <testCase name="boolean" />
-   <testCase name="charset-in-header">
-      <setting clear_encoding_map="Y" input_encoding="ISO-8859-5" />
-   </testCase>
+   <testCase name="charset-in-header" />
    <testCase name="comment" />
    <testCase name="comparisons" />
    <testCase name="compress" />


[2/2] incubator-freemarker git commit: - Configuration.getTemplate has no "encoding" parameter anymore. Similarly #include has no "encoding" parameter either. The charset of templates can be specified via Configuration.defaultEncoding and Configuration.t

Posted by dd...@apache.org.
- Configuration.getTemplate has no "encoding" parameter anymore. Similarly #include has no "encoding" parameter either. The charset of templates can be specified via Configuration.defaultEncoding and Configuration.templateConfigurations (for example based on the directory it is in), or wirh the #ftl directive inside the template. Thus, a given template always has the same charset, no mater how it's accessed.

- Removed Configuration.setEncoding(java.util.Locale, String) and the related other methods. Because of the new logic of template encodings, the locale to encoding mapping doesn't make much sense anymore.
- #include-d/#import-ed templates don't inheirit the charset (encoding) of the #include-ing/#import-ing template. (Because, again, the charset of a template file is independent of how you access it.)
- Require customLookupCondition-s to be Serializable.


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

Branch: refs/heads/3
Commit: f6a693c5734130b82aa5f3c40824f27fb86355e7
Parents: e365f11
Author: ddekany <dd...@apache.org>
Authored: Mon Mar 20 10:28:02 2017 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Mar 20 18:32:10 2017 +0100

----------------------------------------------------------------------
 .../apache/freemarker/core/ASTDirInclude.java   |  49 +--
 .../apache/freemarker/core/Configuration.java   | 253 ++-------------
 .../org/apache/freemarker/core/Environment.java |  61 ++--
 .../apache/freemarker/core/ParameterRole.java   |   1 -
 .../org/apache/freemarker/core/Template.java    |  25 +-
 .../freemarker/core/TemplateConfiguration.java  |   6 +-
 .../core/TemplateNotFoundException.java         |   3 +-
 .../templateresolver/GetTemplateResult.java     |   3 +-
 .../templateresolver/TemplateLoaderSession.java |   3 +-
 .../templateresolver/TemplateLookupContext.java |   2 +-
 .../core/templateresolver/TemplateResolver.java |  10 +-
 .../impl/DefaultTemplateResolver.java           | 102 +++---
 .../freemarker/dom/JaxenXPathSupport.java       |   6 +-
 .../freemarker/servlet/FreemarkerServlet.java   |   3 +-
 src/main/javacc/FTL.jj                          |  10 +-
 src/manual/en_US/FM3-CHANGE-LOG.txt             |  17 +-
 .../freemarker/core/ConfigurationTest.java      | 132 ++------
 .../freemarker/core/TemplatGetEncodingTest.java |  87 -----
 ...igurationWithDefaltTemplateResolverTest.java | 260 +++++++++++++++
 ...teConfigurationWithTemplateResolverTest.java | 321 -------------------
 .../core/TemplateGetEncodingTest.java           |  59 ++++
 .../core/TemplateLookupStrategyTest.java        |  78 +++--
 .../core/TemplateNotFoundMessageTest.java       |   8 +-
 .../DefaultTemplateResolverTest.java            | 136 +-------
 .../test/templatesuite/TemplateTestCase.java    |   4 -
 .../test/templatesuite/expected/include2.txt    |   5 -
 .../templates/charset-in-header_inc2.ftl        |   2 +-
 .../templates/include2-included-encoding.ftl    |  20 --
 .../test/templatesuite/templates/include2.ftl   |   6 -
 .../freemarker/test/templatesuite/testcases.xml |   5 +-
 30 files changed, 562 insertions(+), 1115 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/src/main/java/org/apache/freemarker/core/ASTDirInclude.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ASTDirInclude.java b/src/main/java/org/apache/freemarker/core/ASTDirInclude.java
index 9a51f16..46f71f3 100644
--- a/src/main/java/org/apache/freemarker/core/ASTDirInclude.java
+++ b/src/main/java/org/apache/freemarker/core/ASTDirInclude.java
@@ -21,52 +21,26 @@ package org.apache.freemarker.core;
 
 import java.io.IOException;
 
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateScalarModel;
 import org.apache.freemarker.core.templateresolver.MalformedTemplateNameException;
 import org.apache.freemarker.core.util.BugException;
 import org.apache.freemarker.core.util._StringUtil;
 
-
 /**
  * AST directive node: {@code #include} 
  */
 final class ASTDirInclude extends ASTDirective {
 
-    private final ASTExpression includedTemplateNameExp, encodingExp, ignoreMissingExp;
-    private final String encoding;
+    private final ASTExpression includedTemplateNameExp, ignoreMissingExp;
     private final Boolean ignoreMissingExpPrecalcedValue;
 
     /**
      * @param template the template that this <tt>#include</tt> is a part of.
      * @param includedTemplateNameExp the path of the template to be included.
-     * @param encodingExp the encoding to be used or null, if it's the default.
      */
     ASTDirInclude(Template template,
             ASTExpression includedTemplateNameExp,
-            ASTExpression encodingExp, ASTExpression ignoreMissingExp) throws ParseException {
+            ASTExpression ignoreMissingExp) throws ParseException {
         this.includedTemplateNameExp = includedTemplateNameExp;
-        
-        this.encodingExp = encodingExp;
-        if (encodingExp == null) {
-            encoding = null;
-        } else {
-            if (encodingExp.isLiteral()) {
-                try {
-                    TemplateModel tm = encodingExp.eval(null);
-                    if (!(tm instanceof TemplateScalarModel)) {
-                        throw new ParseException("Expected a string as the value of the \"encoding\" argument",
-                                encodingExp);
-                    }
-                    encoding = ((TemplateScalarModel) tm).getAsString();
-                } catch (TemplateException e) {
-                    // evaluation of literals must not throw a TemplateException
-                    throw new BugException(e);
-                }
-            } else {
-                encoding = null;
-            }
-        }
 
         this.ignoreMissingExp = ignoreMissingExp;
         if (ignoreMissingExp != null && ignoreMissingExp.isLiteral()) {
@@ -99,12 +73,6 @@ final class ASTDirInclude extends ASTDirective {
                     e.getMalformednessDescription());
         }
         
-        final String encoding = this.encoding != null
-                ? this.encoding
-                : (encodingExp != null
-                        ? encodingExp.evalAndCoerceToPlainText(env)
-                        : null);
-        
         final boolean ignoreMissing;
         if (ignoreMissingExpPrecalcedValue != null) {
             ignoreMissing = ignoreMissingExpPrecalcedValue.booleanValue();
@@ -116,7 +84,7 @@ final class ASTDirInclude extends ASTDirective {
         
         final Template includedTemplate;
         try {
-            includedTemplate = env.getTemplateForInclusion(fullIncludedTemplateName, encoding, ignoreMissing);
+            includedTemplate = env.getTemplateForInclusion(fullIncludedTemplateName, ignoreMissing);
         } catch (IOException e) {
             throw new _MiscTemplateException(e, env,
                     "Template inclusion failed (for parameter value ",
@@ -137,9 +105,6 @@ final class ASTDirInclude extends ASTDirective {
         buf.append(getNodeTypeSymbol());
         buf.append(' ');
         buf.append(includedTemplateNameExp.getCanonicalForm());
-        if (encodingExp != null) {
-            buf.append(" encoding=").append(encodingExp.getCanonicalForm());
-        }
         if (ignoreMissingExp != null) {
             buf.append(" ignore_missing=").append(ignoreMissingExp.getCanonicalForm());
         }
@@ -154,15 +119,14 @@ final class ASTDirInclude extends ASTDirective {
     
     @Override
     int getParameterCount() {
-        return 3;
+        return 2;
     }
 
     @Override
     Object getParameterValue(int idx) {
         switch (idx) {
         case 0: return includedTemplateNameExp;
-        case 1: return encodingExp;
-        case 2: return ignoreMissingExp;
+        case 1: return ignoreMissingExp;
         default: throw new IndexOutOfBoundsException();
         }
     }
@@ -171,8 +135,7 @@ final class ASTDirInclude extends ASTDirective {
     ParameterRole getParameterRole(int idx) {
         switch (idx) {
         case 0: return ParameterRole.TEMPLATE_NAME;
-        case 1: return ParameterRole.ENCODING_PARAMETER;
-        case 2: return ParameterRole.IGNORE_MISSING_PARAMETER;
+        case 1: return ParameterRole.IGNORE_MISSING_PARAMETER;
         default: throw new IndexOutOfBoundsException();
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/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 e58ca5b..c5d290f 100644
--- a/src/main/java/org/apache/freemarker/core/Configuration.java
+++ b/src/main/java/org/apache/freemarker/core/Configuration.java
@@ -22,6 +22,7 @@ package org.apache.freemarker.core;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.Serializable;
 import java.text.SimpleDateFormat;
 import java.util.Collection;
 import java.util.Collections;
@@ -38,8 +39,6 @@ import java.util.Properties;
 import java.util.Set;
 import java.util.TimeZone;
 import java.util.TreeSet;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
 
 import org.apache.freemarker.core.model.ObjectWrapper;
 import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper;
@@ -439,8 +438,7 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
     private HashMap<String, Object> rewrappableSharedVariables = null;
     
     private String defaultEncoding = getDefaultDefaultEncoding();
-    private ConcurrentMap localeToCharsetMap = new ConcurrentHashMap();
-    
+
     /**
      * @deprecated Use {@link #Configuration(Version)} instead. Note that the version can be still modified later with
      *     {@link Configuration#setIncompatibleImprovements(Version)} (or
@@ -580,7 +578,6 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
         try {
             Configuration copy = (Configuration) super.clone();
             copy.sharedVariables = new HashMap(sharedVariables);
-            copy.localeToCharsetMap = new ConcurrentHashMap(localeToCharsetMap);
             copy.recreateTemplateResolverWith(
                     templateResolver.getTemplateLoader(), templateResolver.getCacheStorage(),
                     templateResolver.getTemplateLookupStrategy(), templateResolver.getTemplateNameFormat(),
@@ -598,112 +595,7 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
         sharedVariables.put("normalize_newlines", new NormalizeNewlines());
         sharedVariables.put("xml_escape", new XmlEscape());
     }
-    
-    /**
-     * Loads a preset language-to-encoding map, similarly as if you have called
-     * {@link #clearEncodingMap()} and then did multiple {@link #setEncoding(Locale, String)} calls.
-     * It assumes the usual character encodings for most languages.
-     * The previous content of the encoding map will be lost.
-     * This default map currently contains the following mappings:
-     * 
-     * <table style="width: auto; border-collapse: collapse" border="1" summary="preset language to encoding mapping">
-     *   <tr><td>ar</td><td>ISO-8859-6</td></tr>
-     *   <tr><td>be</td><td>ISO-8859-5</td></tr>
-     *   <tr><td>bg</td><td>ISO-8859-5</td></tr>
-     *   <tr><td>ca</td><td>ISO-8859-1</td></tr>
-     *   <tr><td>cs</td><td>ISO-8859-2</td></tr>
-     *   <tr><td>da</td><td>ISO-8859-1</td></tr>
-     *   <tr><td>de</td><td>ISO-8859-1</td></tr>
-     *   <tr><td>el</td><td>ISO-8859-7</td></tr>
-     *   <tr><td>en</td><td>ISO-8859-1</td></tr>
-     *   <tr><td>es</td><td>ISO-8859-1</td></tr>
-     *   <tr><td>et</td><td>ISO-8859-1</td></tr>
-     *   <tr><td>fi</td><td>ISO-8859-1</td></tr>
-     *   <tr><td>fr</td><td>ISO-8859-1</td></tr>
-     *   <tr><td>hr</td><td>ISO-8859-2</td></tr>
-     *   <tr><td>hu</td><td>ISO-8859-2</td></tr>
-     *   <tr><td>is</td><td>ISO-8859-1</td></tr>
-     *   <tr><td>it</td><td>ISO-8859-1</td></tr>
-     *   <tr><td>iw</td><td>ISO-8859-8</td></tr>
-     *   <tr><td>ja</td><td>Shift_JIS</td></tr>
-     *   <tr><td>ko</td><td>EUC-KR</td></tr>    
-     *   <tr><td>lt</td><td>ISO-8859-2</td></tr>
-     *   <tr><td>lv</td><td>ISO-8859-2</td></tr>
-     *   <tr><td>mk</td><td>ISO-8859-5</td></tr>
-     *   <tr><td>nl</td><td>ISO-8859-1</td></tr>
-     *   <tr><td>no</td><td>ISO-8859-1</td></tr>
-     *   <tr><td>pl</td><td>ISO-8859-2</td></tr>
-     *   <tr><td>pt</td><td>ISO-8859-1</td></tr>
-     *   <tr><td>ro</td><td>ISO-8859-2</td></tr>
-     *   <tr><td>ru</td><td>ISO-8859-5</td></tr>
-     *   <tr><td>sh</td><td>ISO-8859-5</td></tr>
-     *   <tr><td>sk</td><td>ISO-8859-2</td></tr>
-     *   <tr><td>sl</td><td>ISO-8859-2</td></tr>
-     *   <tr><td>sq</td><td>ISO-8859-2</td></tr>
-     *   <tr><td>sr</td><td>ISO-8859-5</td></tr>
-     *   <tr><td>sv</td><td>ISO-8859-1</td></tr>
-     *   <tr><td>tr</td><td>ISO-8859-9</td></tr>
-     *   <tr><td>uk</td><td>ISO-8859-5</td></tr>
-     *   <tr><td>zh</td><td>GB2312</td></tr>
-     *   <tr><td>zh_TW</td><td>Big5</td></tr>
-     * </table>
-     * 
-     * @see #clearEncodingMap()
-     * @see #setEncoding(Locale, String)
-     * @see #setDefaultEncoding(String)
-     */
-    public void loadBuiltInEncodingMap() {
-        localeToCharsetMap.clear();
-        localeToCharsetMap.put("ar", "ISO-8859-6");
-        localeToCharsetMap.put("be", "ISO-8859-5");
-        localeToCharsetMap.put("bg", "ISO-8859-5");
-        localeToCharsetMap.put("ca", "ISO-8859-1");
-        localeToCharsetMap.put("cs", "ISO-8859-2");
-        localeToCharsetMap.put("da", "ISO-8859-1");
-        localeToCharsetMap.put("de", "ISO-8859-1");
-        localeToCharsetMap.put("el", "ISO-8859-7");
-        localeToCharsetMap.put("en", "ISO-8859-1");
-        localeToCharsetMap.put("es", "ISO-8859-1");
-        localeToCharsetMap.put("et", "ISO-8859-1");
-        localeToCharsetMap.put("fi", "ISO-8859-1");
-        localeToCharsetMap.put("fr", "ISO-8859-1");
-        localeToCharsetMap.put("hr", "ISO-8859-2");
-        localeToCharsetMap.put("hu", "ISO-8859-2");
-        localeToCharsetMap.put("is", "ISO-8859-1");
-        localeToCharsetMap.put("it", "ISO-8859-1");
-        localeToCharsetMap.put("iw", "ISO-8859-8");
-        localeToCharsetMap.put("ja", "Shift_JIS");
-        localeToCharsetMap.put("ko", "EUC-KR");    
-        localeToCharsetMap.put("lt", "ISO-8859-2");
-        localeToCharsetMap.put("lv", "ISO-8859-2");
-        localeToCharsetMap.put("mk", "ISO-8859-5");
-        localeToCharsetMap.put("nl", "ISO-8859-1");
-        localeToCharsetMap.put("no", "ISO-8859-1");
-        localeToCharsetMap.put("pl", "ISO-8859-2");
-        localeToCharsetMap.put("pt", "ISO-8859-1");
-        localeToCharsetMap.put("ro", "ISO-8859-2");
-        localeToCharsetMap.put("ru", "ISO-8859-5");
-        localeToCharsetMap.put("sh", "ISO-8859-5");
-        localeToCharsetMap.put("sk", "ISO-8859-2");
-        localeToCharsetMap.put("sl", "ISO-8859-2");
-        localeToCharsetMap.put("sq", "ISO-8859-2");
-        localeToCharsetMap.put("sr", "ISO-8859-5");
-        localeToCharsetMap.put("sv", "ISO-8859-1");
-        localeToCharsetMap.put("tr", "ISO-8859-9");
-        localeToCharsetMap.put("uk", "ISO-8859-5");
-        localeToCharsetMap.put("zh", "GB2312");
-        localeToCharsetMap.put("zh_TW", "Big5");
-    }
-
-    /**
-     * Clears language-to-encoding map.
-     * @see #loadBuiltInEncodingMap
-     * @see #setEncoding
-     */
-    public void clearEncodingMap() {
-        localeToCharsetMap.clear();
-    }
-    
+
     /**
      * Sets a {@link TemplateLoader} that is used to look up and load templates;
      * as a side effect the template templateResolver will be emptied.
@@ -1894,53 +1786,44 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
      * missing/staled.
      * 
      * <p>
-     * This is a shorthand for {@link #getTemplate(String, Locale, Object, String, boolean)
-     * getTemplate(name, null, null, null, false)}; see more details there.
+     * This is a shorthand for {@link #getTemplate(String, Locale, Serializable, boolean)
+     * getTemplate(name, null, null, false)}; see more details there.
      * 
      * <p>
      * See {@link Configuration} for an example of basic usage.
      */
     public Template getTemplate(String name)
             throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException {
-        return getTemplate(name, null, null, null, false);
+        return getTemplate(name, null, null, false);
     }
 
     /**
-     * Shorthand for {@link #getTemplate(String, Locale, Object, String, boolean)
+     * Shorthand for {@link #getTemplate(String, Locale, Serializable, boolean)
      * getTemplate(name, locale, null, null, false)}.
      */
     public Template getTemplate(String name, Locale locale)
             throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException {
-        return getTemplate(name, locale, null, null, false);
+        return getTemplate(name, locale, null, false);
     }
 
     /**
-     * Shorthand for {@link #getTemplate(String, Locale, Object, String, boolean)
-     * getTemplate(name, null, null, encoding, false)}.
+     * Shorthand for {@link #getTemplate(String, Locale, Serializable, boolean)
+     * getTemplate(name, locale, customLookupCondition, false)}.
      */
-    public Template getTemplate(String name, String encoding)
+    public Template getTemplate(String name, Locale locale, Serializable customLookupCondition)
             throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException {
-        return getTemplate(name, null, null, encoding, false);
+        return getTemplate(name, locale, customLookupCondition, false);
     }
 
     /**
-     * Shorthand for {@link #getTemplate(String, Locale, Object, String, boolean)
-     * getTemplate(name, locale, null, encoding, false)}.
-     */
-    public Template getTemplate(String name, Locale locale, String encoding)
-            throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException {
-        return getTemplate(name, locale, null, encoding, false);
-    }
-
-    /**
-     * Shorthand for {@link #getTemplate(String, Locale, Object, String, boolean)
-     * getTemplate(name, locale, null, encoding, ignoreMissing)}.
+     * Shorthand for {@link #getTemplate(String, Locale, Serializable, boolean)
+     * getTemplate(name, locale, null, ignoreMissing)}.
      * 
      * @since 2.3.21
      */
-    public Template getTemplate(String name, Locale locale, String encoding, boolean ignoreMissing)
+    public Template getTemplate(String name, Locale locale, boolean ignoreMissing)
             throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException {
-        return getTemplate(name, locale, null, encoding, ignoreMissing);
+        return getTemplate(name, locale, null, ignoreMissing);
     }
     
     /**
@@ -1996,19 +1879,6 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
      *            custom {@link TemplateLookupStrategy}. See also:
      *            {@link TemplateLookupContext#getCustomLookupCondition()}.
      *
-     * @param encoding
-     *            Deprecated mechanism, {@code null} is the recommended; the charset used to interpret the template
-     *            source code bytes (if it's read from a binary source). Can be {@code null} since 2.3.22, in which case
-     *            it will default to {@link Configuration#getEncoding(Locale)} where {@code Locale} is the
-     *            {@code locale} parameter (when {@code locale} was {@code null} too, the its default value is used
-     *            instead). Why is this deprecated: It doesn't make sense to get the <em>same</em> template with
-     *            different encodings, hence, it's error prone to specify the encoding where you get the template.
-     *            Instead, if you have template "files" with different charsets, you should use
-     *            {@link #setTemplateConfigurations(TemplateConfigurationFactory)}, where you can associate encodings to
-     *            individual templates based on their names (like which "directory" are they in, what's their file
-     *            extension, etc.). The encoding associated with the templates that way overrides the encoding that you
-     *            specify here.
-     *
      * @param ignoreMissing
      *            If {@code true}, the method won't throw {@link TemplateNotFoundException} if the template doesn't
      *            exist, instead it returns {@code null}. Other kind of exceptions won't be suppressed.
@@ -2029,17 +1899,13 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
      * 
      * @since 2.3.22
      */
-    public Template getTemplate(String name, Locale locale, Object customLookupCondition,
-            String encoding, boolean ignoreMissing)
+    public Template getTemplate(String name, Locale locale, Serializable customLookupCondition, boolean
+            ignoreMissing)
             throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException {
         if (locale == null) {
             locale = getLocale();
         }
-        if (encoding == null) {
-            encoding = getEncoding(locale);
-        }
-        
-        final GetTemplateResult maybeTemp = templateResolver.getTemplate(name, locale, customLookupCondition, encoding);
+        final GetTemplateResult maybeTemp = templateResolver.getTemplate(name, locale, customLookupCondition);
         final Template temp = maybeTemp.getTemplate();
         if (temp == null) {
             if (ignoreMissing) {
@@ -2112,18 +1978,19 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
     }
 
     /**
-     * Sets the charset used for decoding byte sequences to character sequences when
-     * reading template files in a locale for which no explicit encoding
-     * was specified via {@link #setEncoding(Locale, String)}. Note that by default there is no locale specified for
-     * any locale, so the default encoding is always in effect.
-     * 
+     * Sets the charset used for decoding template files when there's no matching
+     * {@linkplain #getTemplateConfigurations() template configuration} that specifies
+     * 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
+     * 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
      * 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.
-     * 
-     * <p>Note that individual templates may specify their own charset by starting with
-     * <tt>&lt;#ftl encoding="..."&gt;</tt>
-     * 
+     *
      * @param encoding The name of the charset, such as {@code "UTF-8"} or {@code "ISO-8859-1"}
      */
     public void setDefaultEncoding(String encoding) {
@@ -2171,48 +2038,6 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
     }
 
     /**
-     * Gets the preferred character encoding for the given locale, or the 
-     * default encoding if no encoding is set explicitly for the specified
-     * locale. You can associate encodings with locales using 
-     * {@link #setEncoding(Locale, String)} or {@link #loadBuiltInEncodingMap()}.
-     */
-    public String getEncoding(Locale locale) {
-        if (localeToCharsetMap.isEmpty()) {
-            return defaultEncoding;
-        } else {
-            // Try for a full name match (may include country and variant)
-            String charset = (String) localeToCharsetMap.get(locale.toString());
-            if (charset == null) {
-                if (locale.getVariant().length() > 0) {
-                    Locale l = new Locale(locale.getLanguage(), locale.getCountry());
-                    charset = (String) localeToCharsetMap.get(l.toString());
-                    if (charset != null) {
-                        localeToCharsetMap.put(locale.toString(), charset);
-                    }
-                } 
-                charset = (String) localeToCharsetMap.get(locale.getLanguage());
-                if (charset != null) {
-                    localeToCharsetMap.put(locale.toString(), charset);
-                }
-            }
-            return charset != null ? charset : defaultEncoding;
-        }
-    }
-
-    /**
-     * Sets the character set encoding to use for templates of
-     * a given locale. If there is no explicit encoding set for some
-     * locale, then the default encoding will be used, what you can
-     * set with {@link #setDefaultEncoding}.
-     *
-     * @see #clearEncodingMap
-     * @see #loadBuiltInEncodingMap
-     */
-    public void setEncoding(Locale locale, String encoding) {
-        localeToCharsetMap.put(locale.toString(), encoding);
-    }
-
-    /**
      * Adds a shared variable to the configuration.
      * Shared sharedVariables are sharedVariables that are visible
      * as top-level sharedVariables for all templates which use this
@@ -2377,8 +2202,7 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
      * @since 2.3.19
      */
     public void removeTemplateFromCache(String name) throws IOException {
-        Locale loc = getLocale();
-        removeTemplateFromCache(name, loc, getEncoding(loc));
+        removeTemplateFromCache(name, getLocale());
     }
 
     /**
@@ -2386,15 +2210,7 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
      * @since 2.3.19
      */
     public void removeTemplateFromCache(String name, Locale locale) throws IOException {
-        removeTemplateFromCache(name, locale, getEncoding(locale));
-    }
-
-    /**
-     * Equivalent to <tt>removeTemplateFromCache(name, thisCfg.getLocale(), encoding, true)</tt>.
-     * @since 2.3.19
-     */
-    public void removeTemplateFromCache(String name, String encoding) throws IOException {
-        removeTemplateFromCache(name, getLocale(), encoding);
+        removeTemplateFromCache(name, locale, null);
     }
 
     /**
@@ -2404,14 +2220,15 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
      * alone does.
      * 
      * <p>For the meaning of the parameters, see
-     * {@link #getTemplate(String, Locale, String, boolean)}.
+     * {@link #getTemplate(String, Locale, Serializable, boolean)}.
      * 
      * <p>This method is thread-safe and can be called while the engine processes templates.
      * 
      * @since 2.3.19
      */
-    public void removeTemplateFromCache(String name, Locale locale, String encoding) throws IOException {
-        templateResolver.removeTemplateFromCache(name, locale, encoding);
+    public void removeTemplateFromCache(String name, Locale locale, Serializable customLookupCondition)
+            throws IOException {
+        templateResolver.removeTemplateFromCache(name, locale, customLookupCondition);
     }    
     
     /**

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/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 cac703d..7eac791 100644
--- a/src/main/java/org/apache/freemarker/core/Environment.java
+++ b/src/main/java/org/apache/freemarker/core/Environment.java
@@ -21,6 +21,7 @@ package org.apache.freemarker.core;
 
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.io.Serializable;
 import java.io.StringWriter;
 import java.io.Writer;
 import java.sql.Time;
@@ -2368,21 +2369,19 @@ public final class Environment extends Configurable {
      * separately call these two methods, so you can determine the source of exceptions more precisely, and thus achieve
      * more intelligent error handling.
      *
-     * @see #getTemplateForInclusion(String name, String encoding, boolean parse)
+     * @see #getTemplateForInclusion(String, boolean)
      * @see #include(Template includedTemplate)
      */
-    public void include(String name, String encoding, boolean parse)
-            throws IOException, TemplateException {
-        include(getTemplateForInclusion(name, encoding, parse));
+    public void include(String name, boolean parse) throws IOException, TemplateException {
+        include(getTemplateForInclusion(name, parse));
     }
 
     /**
-     * Same as {@link #getTemplateForInclusion(String, String, boolean)} with {@code false}
+     * Same as {@link #getTemplateForInclusion(String, boolean)} with {@code false}
      * {@code ignoreMissing} argument.
      */
-    public Template getTemplateForInclusion(String name, String encoding)
-            throws IOException {
-        return getTemplateForInclusion(name, encoding, false);
+    public Template getTemplateForInclusion(String name) throws IOException {
+        return getTemplateForInclusion(name, false);
     }
 
     /**
@@ -2396,54 +2395,34 @@ public final class Environment extends Configurable {
      *            currently executing template file). (Note that you can use
      *            {@link TemplateResolver#toRootBasedName(String, String)} to convert paths to template root based
      *            paths.) For more details see the identical parameter of
-     *            {@link Configuration#getTemplate(String, Locale, String, boolean)}
-     * 
-     * @param encoding
-     *            the charset of the obtained template. If {@code null}, the encoding of the top template that is
-     *            currently being processed in this {@link Environment} is used, which can lead to odd situations, so
-     *            using {@code null} is not recommended. In most applications, the value of
-     *            {@link Configuration#getEncoding(Locale)} (or {@link Configuration#getDefaultEncoding()}) should be
-     *            used here.
+     *            {@link Configuration#getTemplate(String, Locale, Serializable, boolean)}
      *
      * @param ignoreMissing
-     *            See identical parameter of {@link Configuration#getTemplate(String, Locale, String, boolean)}
+     *            See identical parameter of {@link Configuration#getTemplate(String, Locale, Serializable, boolean)}
      * 
-     * @return Same as {@link Configuration#getTemplate(String, Locale, String, boolean)}
+     * @return Same as {@link Configuration#getTemplate(String, Locale, Serializable, boolean)}
      * @throws IOException
      *             Same as exceptions thrown by
-     *             {@link Configuration#getTemplate(String, Locale, String, boolean)}
+     *             {@link Configuration#getTemplate(String, Locale, Serializable, boolean)}
      * 
      * @since 2.3.21
      */
-    public Template getTemplateForInclusion(String name, String encoding, boolean ignoreMissing)
+    public Template getTemplateForInclusion(String name, boolean ignoreMissing)
             throws IOException {
-        return configuration.getTemplate(
-                name, getLocale(), getIncludedTemplateCustomLookupCondition(),
-                encoding != null ? encoding : getIncludedTemplateEncoding(),
-                ignoreMissing);
+        return configuration.getTemplate(name, getLocale(), getIncludedTemplateCustomLookupCondition(), ignoreMissing);
     }
 
-    private Object getIncludedTemplateCustomLookupCondition() {
+    private Serializable getIncludedTemplateCustomLookupCondition() {
         return getCurrentTemplate().getCustomLookupCondition();
     }
 
-    private String getIncludedTemplateEncoding() {
-        String encoding;
-        // [FM3] This branch shouldn't exist, as it doesn't make much sense to inherit encoding. But we have to keep BC.
-        encoding = getCurrentTemplate().getEncoding();
-        if (encoding == null) {
-            encoding = configuration.getEncoding(getLocale());
-        }
-        return encoding;
-    }
-
     /**
      * Processes a Template in the context of this <code>Environment</code>, including its output in the
      * <code>Environment</code>'s Writer.
      *
      * @param includedTemplate
      *            the template to process. Note that it does <em>not</em> need to be a template returned by
-     *            {@link #getTemplateForInclusion(String name, String encoding, boolean parse)}.
+     *            {@link #getTemplateForInclusion(String, boolean)}.
      */
     public void include(Template includedTemplate)
             throws TemplateException, IOException {
@@ -2522,7 +2501,7 @@ public final class Environment extends Configurable {
      *            paths.)
      */
     public Template getTemplateForImporting(String name) throws IOException {
-        return getTemplateForInclusion(name, null, true);
+        return getTemplateForInclusion(name, true);
     }
 
     /**
@@ -2767,8 +2746,7 @@ public final class Environment extends Configurable {
         
         private final String templateName;
         private final Locale locale;
-        private final String encoding;
-        private final Object customLookupCondition;
+        private final Serializable customLookupCondition;
         
         private InitializationStatus status = InitializationStatus.UNINITIALIZED;
         
@@ -2782,7 +2760,6 @@ public final class Environment extends Configurable {
             this.templateName = templateName;
             // Make snapshot of all settings that influence template resolution:
             locale = getLocale();
-            encoding = getIncludedTemplateEncoding();
             customLookupCondition = getIncludedTemplateCustomLookupCondition();
         }
 
@@ -2821,9 +2798,7 @@ public final class Environment extends Configurable {
         }
 
         private void initialize() throws IOException, TemplateException {
-            setTemplate(configuration.getTemplate(
-                    templateName, locale, customLookupCondition, encoding,
-                    false));
+            setTemplate(configuration.getTemplate(templateName, locale, customLookupCondition, false));
             Locale lastLocale = getLocale();
             try {
                 setLocale(locale);

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/src/main/java/org/apache/freemarker/core/ParameterRole.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ParameterRole.java b/src/main/java/org/apache/freemarker/core/ParameterRole.java
index 1270b1c..146f0b8 100644
--- a/src/main/java/org/apache/freemarker/core/ParameterRole.java
+++ b/src/main/java/org/apache/freemarker/core/ParameterRole.java
@@ -52,7 +52,6 @@ final class ParameterRole {
     static final ParameterRole LIST_SOURCE = new ParameterRole("list source");
     static final ParameterRole TARGET_LOOP_VARIABLE = new ParameterRole("target loop variable");
     static final ParameterRole TEMPLATE_NAME = new ParameterRole("template name");
-    static final ParameterRole ENCODING_PARAMETER = new ParameterRole("\"encoding\" parameter");
     static final ParameterRole IGNORE_MISSING_PARAMETER = new ParameterRole("\"ignore_missing\" parameter");
     static final ParameterRole PARAMETER_NAME = new ParameterRole("parameter name");
     static final ParameterRole PARAMETER_DEFAULT = new ParameterRole("parameter default");

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/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 23096fe..e253197 100644
--- a/src/main/java/org/apache/freemarker/core/Template.java
+++ b/src/main/java/org/apache/freemarker/core/Template.java
@@ -26,6 +26,7 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.PrintStream;
 import java.io.Reader;
+import java.io.Serializable;
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.io.Writer;
@@ -34,6 +35,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Vector;
 
@@ -80,7 +82,7 @@ public class Template extends Configurable {
     private List imports = new Vector();
     private ASTElement rootElement;
     private String encoding, defaultNS;
-    private Object customLookupCondition;
+    private Serializable customLookupCondition;
     private int actualTagSyntax;
     private int actualNamingConvention;
     private boolean autoEscaping;
@@ -567,17 +569,16 @@ public class Template extends Configurable {
 
     /**
      * @param encoding
-     *            The encoding that was used to read this template. When this template {@code #include}-s or
-     *            {@code #import}-s another template, by default it will use this encoding for those. For backward
-     *            compatibility, this can be {@code null}, which will unset this setting.
+     *            The encoding 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 setEncoding(String encoding) {
         this.encoding = encoding;
     }
 
     /**
-     * Returns the default character encoding used for reading included/imported files; if {@code null}, then
-     * the encoding returned by {@link Configuration#getEncoding(java.util.Locale)} should be used instead.
+     * The encoding 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 getEncoding() {
         return encoding;
@@ -585,12 +586,10 @@ public class Template extends Configurable {
     
     /**
      * Gets the custom lookup condition with which this template was found. See the {@code customLookupCondition}
-     * parameter of {@link Configuration#getTemplate(String, java.util.Locale, Object, String, boolean)} for
-     * more explanation.
-     * 
-     * @since 2.3.22
+     * parameter of {@link Configuration#getTemplate(String, Locale, Serializable, boolean)} for more
+     * explanation.
      */
-    public Object getCustomLookupCondition() {
+    public Serializable getCustomLookupCondition() {
         return customLookupCondition;
     }
 
@@ -599,10 +598,8 @@ public class Template extends Configurable {
      * after instantiating the template with its constructor, after a successfull lookup that used this condition. So
      * this should only be called from code that deals with creating new {@code Template} objects, like from
      * {@link DefaultTemplateResolver}.
-     * 
-     * @since 2.3.22
      */
-    public void setCustomLookupCondition(Object customLookupCondition) {
+    public void setCustomLookupCondition(Serializable customLookupCondition) {
         this.customLookupCondition = customLookupCondition;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/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 2e8c0f6..3d1b903 100644
--- a/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java
+++ b/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java
@@ -539,11 +539,7 @@ public final class TemplateConfiguration extends Configurable implements ParserC
 
     /**
      * When the standard template loading/caching mechanism is used, this forces the charset used for reading the
-     * template "file", overriding everything but the encoding coming from the {@code #ftl} header. This setting
-     * overrides the locale-specific encodings set via {@link Configuration#setEncoding(java.util.Locale, String)}. It
-     * also overrides the {@code encoding} parameter of {@link Configuration#getTemplate(String, String)} (and of its
-     * overloads) and the {@code encoding} parameter of the {@code #include} directive. This works like that because
-     * specifying the encoding where you are requesting the template is error prone and deprecated.
+     * template "file", overriding everything but the encoding coming from the {@code #ftl} header.
      * 
      * <p>
      * If you are developing your own template loading/caching mechanism instead of the standard one, note that the

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/src/main/java/org/apache/freemarker/core/TemplateNotFoundException.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/TemplateNotFoundException.java b/src/main/java/org/apache/freemarker/core/TemplateNotFoundException.java
index fced93f..37ba911 100644
--- a/src/main/java/org/apache/freemarker/core/TemplateNotFoundException.java
+++ b/src/main/java/org/apache/freemarker/core/TemplateNotFoundException.java
@@ -20,6 +20,7 @@
 package org.apache.freemarker.core;
 
 import java.io.FileNotFoundException;
+import java.io.Serializable;
 
 import org.apache.freemarker.core.templateresolver.MalformedTemplateNameException;
 
@@ -54,7 +55,7 @@ public final class TemplateNotFoundException extends FileNotFoundException {
     /**
      * The custom lookup condition with which the template was requested, or {@code null} if there's no such condition.
      * See the {@code customLookupCondition} parameter of
-     * {@link Configuration#getTemplate(String, java.util.Locale, Object, String, boolean)}.
+     * {@link Configuration#getTemplate(String, java.util.Locale, Serializable, boolean)}.
      */
     public Object getCustomLookupCondition() {
         return customLookupCondition;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/src/main/java/org/apache/freemarker/core/templateresolver/GetTemplateResult.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/templateresolver/GetTemplateResult.java b/src/main/java/org/apache/freemarker/core/templateresolver/GetTemplateResult.java
index 2260267..58c9ea9 100644
--- a/src/main/java/org/apache/freemarker/core/templateresolver/GetTemplateResult.java
+++ b/src/main/java/org/apache/freemarker/core/templateresolver/GetTemplateResult.java
@@ -18,12 +18,13 @@
  */
 package org.apache.freemarker.core.templateresolver;
 
+import java.io.Serializable;
 import java.util.Locale;
 
 import org.apache.freemarker.core.Template;
 
 /**
- * Used for the return value of {@link TemplateResolver#getTemplate(String, Locale, Object, String)}.
+ * Used for the return value of {@link TemplateResolver#getTemplate(String, Locale, Serializable)} .
  * 
  * @since 3.0.0
  */

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/src/main/java/org/apache/freemarker/core/templateresolver/TemplateLoaderSession.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/templateresolver/TemplateLoaderSession.java b/src/main/java/org/apache/freemarker/core/templateresolver/TemplateLoaderSession.java
index 7d6f7a6..6bf1b1f 100644
--- a/src/main/java/org/apache/freemarker/core/templateresolver/TemplateLoaderSession.java
+++ b/src/main/java/org/apache/freemarker/core/templateresolver/TemplateLoaderSession.java
@@ -21,6 +21,7 @@ package org.apache.freemarker.core.templateresolver;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.Reader;
+import java.io.Serializable;
 
 import org.apache.freemarker.core.templateresolver.impl.DefaultTemplateResolver;
 
@@ -28,7 +29,7 @@ import org.apache.freemarker.core.templateresolver.impl.DefaultTemplateResolver;
  * Stores shared state between {@link TemplateLoader} operations that are executed close to each other in the same
  * thread. For example, a {@link TemplateLoader} that reads from a database might wants to store the database
  * connection in it for reuse. The goal of sessions is mostly to increase performance. However, because a
- * {@link DefaultTemplateResolver#getTemplate(String, java.util.Locale, Object, String)} call is executed inside a single
+ * {@link DefaultTemplateResolver#getTemplate(String, java.util.Locale, Serializable)} call is executed inside a single
  * session, sessions can be also be utilized to ensure that the template lookup (see {@link TemplateLookupStrategy})
  * happens on a consistent view (a snapshot) of the backing storage, if the backing storage mechanism supports such
  * thing.

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/src/main/java/org/apache/freemarker/core/templateresolver/TemplateLookupContext.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/templateresolver/TemplateLookupContext.java b/src/main/java/org/apache/freemarker/core/templateresolver/TemplateLookupContext.java
index 3db956c..0a3b33a 100644
--- a/src/main/java/org/apache/freemarker/core/templateresolver/TemplateLookupContext.java
+++ b/src/main/java/org/apache/freemarker/core/templateresolver/TemplateLookupContext.java
@@ -92,7 +92,7 @@ public abstract class TemplateLookupContext<R extends TemplateLookupResult> {
 
     /**
      * Returns the value of the {@code customLookupCondition} parameter of
-     * {@link Configuration#getTemplate(String, Locale, Object, String, boolean)}; see requirements there, such
+     * {@link Configuration#getTemplate(String, Locale, Serializable, boolean)}; see requirements there, such
      * as having a proper {@link Object#equals(Object)} and {@link Object#hashCode()} method. The interpretation of this
      * value is up to the custom {@link TemplateLookupStrategy}. Usually, it's used similarly to as the default lookup
      * strategy uses {@link #getTemplateLocale()}, that is, to look for a template variation that satisfies the

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/src/main/java/org/apache/freemarker/core/templateresolver/TemplateResolver.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/templateresolver/TemplateResolver.java b/src/main/java/org/apache/freemarker/core/templateresolver/TemplateResolver.java
index 1b04ba7..f257e2b 100644
--- a/src/main/java/org/apache/freemarker/core/templateresolver/TemplateResolver.java
+++ b/src/main/java/org/apache/freemarker/core/templateresolver/TemplateResolver.java
@@ -19,6 +19,7 @@
 package org.apache.freemarker.core.templateresolver;
 
 import java.io.IOException;
+import java.io.Serializable;
 import java.util.Locale;
 
 import org.apache.freemarker.core.Configuration;
@@ -62,7 +63,7 @@ public abstract class TemplateResolver {
      * 
      * <p>
      * All parameters must be non-{@code null}, except {@code customLookupCondition}. For the meaning of the parameters
-     * see {@link Configuration#getTemplate(String, Locale, String, boolean)}.
+     * see {@link Configuration#getTemplate(String, Locale, Serializable, boolean)}.
      *
      * @return A {@link GetTemplateResult} object that contains the {@link Template}, or a
      *         {@link GetTemplateResult} object that contains {@code null} as the {@link Template} and information
@@ -82,8 +83,7 @@ public abstract class TemplateResolver {
      *             value.
      */
     // [FM3] This parameters will be removed: String encoding
-    public abstract GetTemplateResult getTemplate(String name, Locale locale, Object customLookupCondition,
-            String encoding)
+    public abstract GetTemplateResult getTemplate(String name, Locale locale, Serializable customLookupCondition)
             throws MalformedTemplateNameException, ParseException, IOException;
 
     /**
@@ -108,7 +108,7 @@ public abstract class TemplateResolver {
      * {@link Configuration#setTemplateUpdateDelayMilliseconds(long)} alone does.
      * 
      * <p>
-     * For the meaning of the parameters, see {@link #getTemplate(String, Locale, Object, String)}
+     * For the meaning of the parameters, see {@link #getTemplate(String, Locale, Serializable)}
      * 
      * <p>
      * This method is thread-safe and can be called while the engine processes templates.
@@ -116,7 +116,7 @@ public abstract class TemplateResolver {
      * @throws UnsupportedOperationException If the {@link TemplateResolver} implementation doesn't support this
      *        operation.
      */
-    public abstract void removeTemplateFromCache(String name, Locale locale, String encoding)
+    public abstract void removeTemplateFromCache(String name, Locale locale, Serializable customLookupCondition)
             throws IOException, UnsupportedOperationException;
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/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 14d04f7..a5a574c 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
@@ -198,7 +198,7 @@ public class DefaultTemplateResolver extends TemplateResolver {
      * 
      * <p>
      * All parameters must be non-{@code null}, except {@code customLookupCondition}. For the meaning of the parameters
-     * see {@link Configuration#getTemplate(String, Locale, String, boolean)}.
+     * see {@link Configuration#getTemplate(String, Locale, Serializable, boolean)}.
      *
      * @return A {@link GetTemplateResult} object that contains the {@link Template}, or a
      *         {@link GetTemplateResult} object that contains {@code null} as the {@link Template} and information
@@ -223,20 +223,18 @@ public class DefaultTemplateResolver extends TemplateResolver {
      * @since 2.3.22
      */
     @Override
-    public GetTemplateResult getTemplate(String name, Locale locale, Object customLookupCondition,
-            String encoding)
+    public GetTemplateResult getTemplate(String name, Locale locale, Serializable customLookupCondition)
     throws IOException {
         _NullArgumentException.check("name", name);
         _NullArgumentException.check("locale", locale);
-        _NullArgumentException.check("encoding", encoding);
-        
+
         name = templateNameFormat.normalizeRootBasedName(name);
         
         if (templateLoader == null) {
             return new GetTemplateResult(name, "The TemplateLoader (and TemplateLoader2) was null.");
         }
         
-        Template template = getTemplateInternal(name, locale, customLookupCondition, encoding);
+        Template template = getTemplateInternal(name, locale, customLookupCondition);
         return template != null ? new GetTemplateResult(template) : new GetTemplateResult(name, (String) null);
     }
 
@@ -251,14 +249,13 @@ public class DefaultTemplateResolver extends TemplateResolver {
     }
 
     private Template getTemplateInternal(
-            final String name, final Locale locale, final Object customLookupCondition,
-            final String encoding)
+            final String name, final Locale locale, final Serializable customLookupCondition)
     throws IOException {
         final boolean debug = LOG.isDebugEnabled();
         final String debugPrefix = debug
-                ? getDebugPrefix("getTemplate", name, locale, customLookupCondition, encoding)
+                ? getDebugPrefix("getTemplate", name, locale, customLookupCondition)
                 : null;
-        final CachedResultKey cacheKey = new CachedResultKey(name, locale, customLookupCondition, encoding);
+        final CachedResultKey cacheKey = new CachedResultKey(name, locale, customLookupCondition);
         
         CachedResult oldCachedResult = (CachedResult) cacheStorage.get(cacheKey);
         
@@ -387,8 +384,7 @@ public class DefaultTemplateResolver extends TemplateResolver {
             
             Template template = loadTemplate(
                     templateLoaderResult,
-                    name, newLookupResult.getTemplateSourceName(), locale, customLookupCondition,
-                    encoding);
+                    name, newLookupResult.getTemplateSourceName(), locale, customLookupCondition);
             if (session != null) {
                 session.close();
                 if (debug) {
@@ -524,8 +520,8 @@ public class DefaultTemplateResolver extends TemplateResolver {
     @SuppressWarnings("deprecation")
     private Template loadTemplate(
             TemplateLoadingResult templateLoaderResult,
-            final String name, final String sourceName, Locale locale, final Object customLookupCondition,
-            String initialEncoding) throws IOException {
+            final String name, final String sourceName, Locale locale, final Serializable customLookupCondition)
+            throws IOException {
         TemplateConfiguration tc;
         {
             TemplateConfiguration cfgTC;
@@ -552,23 +548,13 @@ public class DefaultTemplateResolver extends TemplateResolver {
             }
         }
 
-        TemplateLanguage templateLanguage = null;
-        if (tc != null) {
-            // TC.{encoding,locale} is stronger than the cfg.getTemplate arguments by design.
-            if (tc.isEncodingSet()) {
-                initialEncoding = tc.getEncoding();
-            }
-            if (tc.isLocaleSet()) {
-                locale = tc.getLocale();
-            }
-            if (tc.isTemplateLanguageSet()) {
-                templateLanguage = tc.getTemplateLanguage();
-            }
+        if (tc != null && tc.isLocaleSet()) {
+            locale = tc.getLocale();
         }
 
-        if (templateLanguage == null) {
-            templateLanguage = config.getTemplateLanguage();
-        }
+        String initialEncoding = tc != null && tc.isEncodingSet() ? tc.getEncoding() : config.getDefaultEncoding();
+        TemplateLanguage templateLanguage = tc != null && tc.isTemplateLanguageSet() ? tc.getTemplateLanguage()
+                : config .getTemplateLanguage();
 
         Template template;
         {
@@ -689,7 +675,7 @@ public class DefaultTemplateResolver extends TemplateResolver {
 
     /**
      * Removes all entries from the cache, forcing reloading of templates on subsequent
-     * {@link #getTemplate(String, Locale, Object, String)} calls.
+     * {@link #getTemplate(String, Locale, Serializable)} calls.
      * 
      * @param resetTemplateLoader
      *            Whether to call {@link TemplateLoader#resetState()}. on the template loader.
@@ -717,25 +703,16 @@ public class DefaultTemplateResolver extends TemplateResolver {
     }
 
     /**
-     * Same as {@link #removeTemplateFromCache(String, Locale, Object, String)} with {@code null}
-     * {@code customLookupCondition}.
-     */
-    @Override
-    public void removeTemplateFromCache(
-            String name, Locale locale, String encoding) throws IOException {
-        removeTemplateFromCache(name, locale, null, encoding);
-    }
-    
-    /**
      * Removes an entry from the cache, hence forcing the re-loading of it when it's next time requested. (It doesn't
      * delete the template file itself.) This is to give the application finer control over cache updating than
      * {@link #setTemplateUpdateDelayMilliseconds(long)} alone does.
      * 
      * For the meaning of the parameters, see
-     * {@link Configuration#getTemplate(String, Locale, Object, String, boolean)}
+     * {@link Configuration#getTemplate(String, Locale, Serializable, boolean)}
      */
+    @Override
     public void removeTemplateFromCache(
-            String name, Locale locale, Object customLookupCondition, String encoding)
+            String name, Locale locale, Serializable customLookupCondition)
     throws IOException {
         if (name == null) {
             throw new IllegalArgumentException("Argument \"name\" can't be null");
@@ -743,16 +720,13 @@ public class DefaultTemplateResolver extends TemplateResolver {
         if (locale == null) {
             throw new IllegalArgumentException("Argument \"locale\" can't be null");
         }
-        if (encoding == null) {
-            throw new IllegalArgumentException("Argument \"encoding\" can't be null");
-        }
         name = templateNameFormat.normalizeRootBasedName(name);
         if (name != null && templateLoader != null) {
             boolean debug = LOG.isDebugEnabled();
             String debugPrefix = debug
-                    ? getDebugPrefix("removeTemplate", name, locale, customLookupCondition, encoding)
+                    ? getDebugPrefix("removeTemplate", name, locale, customLookupCondition)
                     : null;
-            CachedResultKey tk = new CachedResultKey(name, locale, customLookupCondition, encoding);
+            CachedResultKey tk = new CachedResultKey(name, locale, customLookupCondition);
             
             cacheStorage.remove(tk);
             if (debug) {
@@ -761,11 +735,10 @@ public class DefaultTemplateResolver extends TemplateResolver {
         }
     }
 
-    private String getDebugPrefix(String operation, String name, Locale locale, Object customLookupCondition, String encoding) {
+    private String getDebugPrefix(String operation, String name, Locale locale, Object customLookupCondition) {
         return operation + " " + _StringUtil.jQuoteNoXSS(name) + "("
                 + _StringUtil.jQuoteNoXSS(locale)
                 + (customLookupCondition != null ? ", cond=" + _StringUtil.jQuoteNoXSS(customLookupCondition) : "")
-                + ", " + encoding
                 + "): ";
     }    
 
@@ -813,41 +786,38 @@ public class DefaultTemplateResolver extends TemplateResolver {
     private static final class CachedResultKey implements Serializable {
         private final String name;
         private final Locale locale;
-        private final Object customLookupCondition;
-        private final String encoding;
+        private final Serializable customLookupCondition;
 
-        CachedResultKey(String name, Locale locale, Object customLookupCondition, String encoding) {
+        CachedResultKey(String name, Locale locale, Serializable customLookupCondition) {
             this.name = name;
             this.locale = locale;
             this.customLookupCondition = customLookupCondition;
-            this.encoding = encoding;
         }
 
         @Override
         public boolean equals(Object o) {
-            if (o instanceof CachedResultKey) {
-                CachedResultKey tk = (CachedResultKey) o;
-                return
+            if (!(o instanceof CachedResultKey)) {
+                return false;
+            }
+            CachedResultKey tk = (CachedResultKey) o;
+            return
                     name.equals(tk.name) &&
                     locale.equals(tk.locale) &&
-                    nullSafeEquals(customLookupCondition, tk.customLookupCondition) &&
-                    encoding.equals(tk.encoding);
-            }
-            return false;
+                    nullSafeEquals(customLookupCondition, tk.customLookupCondition);
         }
 
         @Override
         public int hashCode() {
-            return
-                name.hashCode() ^
-                locale.hashCode() ^
-                encoding.hashCode() ^
-                (customLookupCondition != null ? customLookupCondition.hashCode() : 0);
+            int result = name.hashCode();
+            result = 31 * result + locale.hashCode();
+            result = 31 * result + (customLookupCondition != null ? customLookupCondition.hashCode() : 0);
+            return result;
         }
+
     }
 
     /**
-     * Hold the a cached {@link #getTemplate(String, Locale, Object, String)} result and the associated
+     * Hold the a cached {@link #getTemplate(String, Locale, Serializable)} result and the associated
      * information needed to check if the cached value is up to date.
      * 
      * <p>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/src/main/java/org/apache/freemarker/dom/JaxenXPathSupport.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/dom/JaxenXPathSupport.java b/src/main/java/org/apache/freemarker/dom/JaxenXPathSupport.java
index cd0724a..0bb3c65 100644
--- a/src/main/java/org/apache/freemarker/dom/JaxenXPathSupport.java
+++ b/src/main/java/org/apache/freemarker/dom/JaxenXPathSupport.java
@@ -194,15 +194,11 @@ class JaxenXPathSupport implements XPathSupport {
     // [FM3] Look into this "hidden" feature
     static Template getTemplate(String systemId) throws IOException {
         Environment env = Environment.getCurrentEnvironment();
-        String encoding = env.getCurrentTemplate().getEncoding(); // [FM3] Encoding shouldn't be inherited anymore
-        if (encoding == null) {
-            encoding = env.getConfiguration().getEncoding(env.getLocale());
-        }
         String templatePath = env.getCurrentTemplate().getName();
         int lastSlash = templatePath.lastIndexOf('/');
         templatePath = lastSlash == -1 ? "" : templatePath.substring(0, lastSlash + 1);
         systemId = env.toFullTemplateName(templatePath, systemId);
-        return env.getConfiguration().getTemplate(systemId, env.getLocale(), encoding, false);
+        return env.getConfiguration().getTemplate(systemId, env.getLocale(), false);
     }
 
     private static InputSource createInputSource(String publicId, Template raw) throws IOException, SAXException {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/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 0fc7cfa..0853133 100644
--- a/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
+++ b/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
@@ -205,8 +205,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
  * that was the only way before Servlet 2.4), not via the more modern
  * {@link HttpServletResponse#setCharacterEncoding(String)} method. Note that the charset of a template usually comes
  * from {@link Configuration#getDefaultEncoding()} (i.e., from the {@code default_encoding} FreeMarker setting),
- * occasionally from {@link Configuration#getEncoding(Locale)} (when FreeMarker was configured to use different charsets
- * depending on the locale) or even more rarely from {@link Configuration#getTemplateConfigurations()} (when FreeMarker was
+ * or occasionally from {@link Configuration#getTemplateConfigurations()} (when FreeMarker was
  * configured to use a specific charset for certain templates).
  * <li>{@value #INIT_PARAM_VALUE_FROM_TEMPLATE}: This should be used in most applications, but it's not the default for
  * backward compatibility. It reads the {@link Configurable#getOutputEncoding()} setting of the template (note that the

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/src/main/javacc/FTL.jj
----------------------------------------------------------------------
diff --git a/src/main/javacc/FTL.jj b/src/main/javacc/FTL.jj
index 2566df6..ac20322 100644
--- a/src/main/javacc/FTL.jj
+++ b/src/main/javacc/FTL.jj
@@ -2935,7 +2935,7 @@ ASTDirInclude Include() :
 {
     ASTExpression nameExp;
     Token att, start, end;
-    ASTExpression exp, encodingExp = null, ignoreMissingExp = null;
+    ASTExpression exp, ignoreMissingExp = null;
 }
 {
     start = <_INCLUDE>
@@ -2947,16 +2947,14 @@ ASTDirInclude Include() :
         exp = ASTExpression()
         {
             String attString = att.image;
-            if (attString.equalsIgnoreCase("encoding")) {
-            	encodingExp = exp;
-            } else if (attString.equalsIgnoreCase("ignore_missing") || attString.equals("ignoreMissing")) {
+            if (attString.equalsIgnoreCase("ignore_missing") || attString.equals("ignoreMissing")) {
                 token_source.checkNamingConvention(att);
             	ignoreMissingExp = exp;
             } else {
                 String correctedName = attString.equals("ignoreMissing") ? "ignore_missing" : null;
                 throw new ParseException(
                 		"Unsupported named #include parameter: \"" + attString + "\". Supported parameters are: "
-                		+ "\"encoding\", \"ignore_missing\"."
+                		+ "\"ignore_missing\"."
                 		+ (correctedName == null
                 		      ? ""
                 		      : " Supporting camelCase parameter names is planned for FreeMarker 2.4.0; "
@@ -2968,7 +2966,7 @@ ASTDirInclude Include() :
     )*
     end = LooseDirectiveEnd()
     {
-        ASTDirInclude result = new ASTDirInclude(template, nameExp, encodingExp, ignoreMissingExp);
+        ASTDirInclude result = new ASTDirInclude(template, nameExp, ignoreMissingExp);
         result.setLocation(template, start, end);
         return result;
     }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/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 6c7a5fb..5330a6a 100644
--- a/src/manual/en_US/FM3-CHANGE-LOG.txt
+++ b/src/manual/en_US/FM3-CHANGE-LOG.txt
@@ -133,7 +133,7 @@ the FreeMarer 3 changelog here:
     In FM2, such overloads has used the global static default DefaltObjectWrapper, but that was removed.
   - If the ObjectWrapper is not a DefaultObjectWrapper (or a subclass of it), `className?new(args)` will only accept 0 arguments.
     (Earlier we have fallen back to using the global static default DefaultObjectWrapper instance to handle argument unwrapping
-    and overloaded constructors.) Note that ?new is only used to instantiate TemplateModel-s, typically, tempalte language
+    and overloaded constructors.) Note that ?new is only used to instantiate TemplateModel-s, typically, template language
     functions/directives implemented in Java, and so they hardly ever has an argument.
   - FreemarkerServlet now requires that the ObjectWrapper it uses implements ObjectWrapperAndUnwrapper. (Thus, the return type
     of FreemarerServlet.createDefaultObjectWrapper() has changed to ObjectWrapperAndUnwrapper.) The unwrapping functionality is
@@ -156,9 +156,18 @@ the FreeMarer 3 changelog here:
 - Removed DefaultObjectWrapper.methodsShadowItems setting, in effect defaulting it to true. This has decided if the generic
   get method (`get(String)`) had priority over methods of similar name. The generic get method is only recognized from its
   name and parameter type, so it's a quite consfusing feature, and might will be removed alltogether.
-- DefaultObjectWrapper is not immutable (has no setter methods), and can only be constructed with DefaultObjectWrapper.Builder
+- DefaultObjectWrapper is now immutable (has no setter methods), and can only be constructed with DefaultObjectWrapper.Builder
 - Configuration.getTemplate has no "parse" parameter anymore. Similarly #include has no "parse" parameter anymore. Whether a
   template is parsed can be specified via Configuration.templateConfigurations, for example based on the file extension. Thus,
   a certain template is either always parsed or never parsed, and whoever gets or include it need not know about that.
-  Also added a new setting, "templateLanguge", which decides this; the two available values are
-  TemplateLanguage.FTL and TemplateLanguage.STATIC_TEXT.
\ No newline at end of file
+  Also added a new setting, "templateLanguage", which decides this; the two available values are
+  TemplateLanguage.FTL and TemplateLanguage.STATIC_TEXT.
+- Configuration.getTemplate has no "encoding" parameter anymore. Similarly #include has no "encoding" parameter either. The charset
+  of templates can be specified via Configuration.defaultEncoding and Configuration.templateConfigurations (for example based on the
+  directory it is in), or wirh the #ftl directive inside the template. Thus, a given template always has the same charset, no mater how
+  it's accessed.
+- #include-d/#import-ed templates don't inheirit the charset (encoding) of the #include-ing/#import-ing template. (Because,
+  again, the charset of a template file is independent of how you access it.)
+- Removed Configuration.setEncoding(java.util.Locale, String) and the related other methods. Because of the new logic of template
+  encodings, the locale to encoding mapping doesn't make much sense anymore.
+- Require customLookupCondition-s to be Serializable.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/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 51cdcc3..6539753 100644
--- a/src/test/java/org/apache/freemarker/core/ConfigurationTest.java
+++ b/src/test/java/org/apache/freemarker/core/ConfigurationTest.java
@@ -24,6 +24,7 @@ import static org.hamcrest.Matchers.*;
 import static org.junit.Assert.*;
 
 import java.io.IOException;
+import java.io.Serializable;
 import java.io.StringWriter;
 import java.lang.reflect.Field;
 import java.nio.charset.StandardCharsets;
@@ -51,6 +52,8 @@ import org.apache.freemarker.core.outputformat.impl.RTFOutputFormat;
 import org.apache.freemarker.core.outputformat.impl.UndefinedOutputFormat;
 import org.apache.freemarker.core.outputformat.impl.XMLOutputFormat;
 import org.apache.freemarker.core.templateresolver.CacheStorageWithGetSize;
+import org.apache.freemarker.core.templateresolver.ConditionalTemplateConfigurationFactory;
+import org.apache.freemarker.core.templateresolver.FileNameGlobMatcher;
 import org.apache.freemarker.core.templateresolver.TemplateLookupContext;
 import org.apache.freemarker.core.templateresolver.TemplateLookupResult;
 import org.apache.freemarker.core.templateresolver.TemplateLookupStrategy;
@@ -249,18 +252,25 @@ public class ConfigurationTest extends TestCase {
         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 Integer custLookupCond = 123;
+        final Serializable custLookupCond = new Serializable() { };
         
         Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
         cfg.setLocale(Locale.GERMAN);
         cfg.setDefaultEncoding(latin1);
-        cfg.setEncoding(hu, latin2);
-        
+
+        TemplateConfiguration huTC = new TemplateConfiguration();
+        huTC.setEncoding(latin2);
+        cfg.setTemplateConfigurations(
+                new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*_hu.*"),
+                huTC));
+
         ByteArrayTemplateLoader tl = new ByteArrayTemplateLoader();
         tl.putTemplate(tFtl, "${1}".getBytes(StandardCharsets.UTF_8));
         tl.putTemplate(tEnFtl, "${1}".getBytes(StandardCharsets.UTF_8));
+        tl.putTemplate(tHuFtl, "${1}".getBytes(StandardCharsets.UTF_8));
         tl.putTemplate(tUtf8Ftl, "<#ftl encoding='utf-8'>".getBytes(StandardCharsets.UTF_8));
         cfg.setTemplateLoader(tl);
         
@@ -282,7 +292,7 @@ public class ConfigurationTest extends TestCase {
             assertEquals(utf8, t.getEncoding());
         }
         
-        // 2 args overload 1:
+        // 2 args:
         {
             Template t = cfg.getTemplate(tFtl, Locale.GERMAN);
             assertEquals(tFtl, t.getName());
@@ -318,7 +328,7 @@ public class ConfigurationTest extends TestCase {
         {
             Template t = cfg.getTemplate(tFtl, hu);
             assertEquals(tFtl, t.getName());
-            assertEquals(tFtl, t.getSourceName());
+            assertEquals(tHuFtl, t.getSourceName());
             assertEquals(hu, t.getLocale());
             assertNull(t.getCustomLookupCondition());
             assertEquals(latin2, t.getEncoding());
@@ -331,55 +341,17 @@ public class ConfigurationTest extends TestCase {
             assertNull(t.getCustomLookupCondition());
             assertEquals(utf8, t.getEncoding());
         }
-        
-        // 2 args overload 2:
-        {
-            Template t = cfg.getTemplate(tFtl, utf8);
-            assertEquals(tFtl, t.getName());
-            assertEquals(tFtl, t.getSourceName());
-            assertEquals(Locale.GERMAN, t.getLocale());
-            assertNull(t.getCustomLookupCondition());
-            assertEquals(utf8, t.getEncoding());
-        }
-        {
-            Template t = cfg.getTemplate(tFtl, (String) null);
-            assertEquals(tFtl, t.getName());
-            assertEquals(tFtl, t.getSourceName());
-            assertEquals(Locale.GERMAN, t.getLocale());
-            assertNull(t.getCustomLookupCondition());
-            assertEquals(latin1, t.getEncoding());
-        }
-        
+
         // 3 args:
-        {
-            Template t = cfg.getTemplate(tFtl, hu, utf8);
-            assertEquals(tFtl, t.getName());
-            assertEquals(tFtl, t.getSourceName());
-            assertEquals(hu, t.getLocale());
-            assertNull(t.getCustomLookupCondition());
-            assertEquals(utf8, t.getEncoding());
-            assertOutputEquals("1", t);
-        }
-        {
-            Template t = cfg.getTemplate(tFtl, hu, null);
-            assertEquals(tFtl, t.getName());
-            assertEquals(tFtl, t.getSourceName());
-            assertEquals(hu, t.getLocale());
-            assertNull(t.getCustomLookupCondition());
-            assertEquals(latin2, t.getEncoding());
-            assertOutputEquals("1", t);
-        }
-        {
-            Template t = cfg.getTemplate(tFtl, null, utf8);
-            assertEquals(tFtl, t.getName());
-            assertEquals(tFtl, t.getSourceName());
-            assertEquals(Locale.GERMAN, t.getLocale());
-            assertNull(t.getCustomLookupCondition());
-            assertEquals(utf8, t.getEncoding());
-            assertOutputEquals("1", t);
+        try {
+            cfg.getTemplate("missing.ftl", hu, false);
+            fail();
+        } catch (TemplateNotFoundException e) {
+            // Expected
         }
+        assertNull(cfg.getTemplate("missing.ftl", hu, true));
         {
-            Template t = cfg.getTemplate(tFtl, null, null);
+            Template t = cfg.getTemplate(tFtl, null, true);
             assertEquals(tFtl, t.getName());
             assertEquals(tFtl, t.getSourceName());
             assertEquals(Locale.GERMAN, t.getLocale());
@@ -387,80 +359,42 @@ public class ConfigurationTest extends TestCase {
             assertEquals(latin1, t.getEncoding());
             assertOutputEquals("1", t);
         }
-        
-        // 4 args:
         {
-            Template t = cfg.getTemplate(tFtl, hu, utf8, true);
+            Template t = cfg.getTemplate(tFtl, hu, true);
             assertEquals(tFtl, t.getName());
-            assertEquals(tFtl, t.getSourceName());
-            assertEquals(hu, t.getLocale());
-            assertNull(t.getCustomLookupCondition());
-            assertEquals(utf8, t.getEncoding());
-            assertOutputEquals("1", t);
-        }
-        {
-            Template t = cfg.getTemplate(tFtl, null, utf8, true);
-            assertEquals(tFtl, t.getName());
-            assertEquals(tFtl, t.getSourceName());
-            assertEquals(Locale.GERMAN, t.getLocale());
-            assertNull(t.getCustomLookupCondition());
-            assertEquals(utf8, t.getEncoding());
-            assertOutputEquals("1", t);
-        }
-        {
-            Template t = cfg.getTemplate(tFtl, hu, null, true);
-            assertEquals(tFtl, t.getName());
-            assertEquals(tFtl, t.getSourceName());
+            assertEquals(tHuFtl, t.getSourceName());
             assertEquals(hu, t.getLocale());
             assertNull(t.getCustomLookupCondition());
             assertEquals(latin2, t.getEncoding());
             assertOutputEquals("1", t);
         }
 
-        // Ignore missing
+        // 4 args:
         try {
-            cfg.getTemplate("missing.ftl", hu, utf8, false);
+            cfg.getTemplate("missing.ftl", hu, custLookupCond, false);
             fail();
         } catch (TemplateNotFoundException e) {
             // Expected
         }
-        assertNull(cfg.getTemplate("missing.ftl", hu, utf8, true));
-        
-        // 5 args:
+        assertNull(cfg.getTemplate("missing.ftl", hu, custLookupCond, true));
         {
-            Template t = cfg.getTemplate(tFtl, hu, custLookupCond, utf8, false);
+            Template t = cfg.getTemplate(tFtl, hu, custLookupCond, false);
             assertEquals(tFtl, t.getName());
-            assertEquals(tFtl, t.getSourceName());
+            assertEquals(tHuFtl, t.getSourceName());
             assertEquals(hu, t.getLocale());
             assertEquals(custLookupCond, t.getCustomLookupCondition());
-            assertEquals(utf8, t.getEncoding());
+            assertEquals(latin2, t.getEncoding());
             assertOutputEquals("1", t);
         }
         {
-            Template t = cfg.getTemplate(tFtl, null, custLookupCond, utf8, false);
+            Template t = cfg.getTemplate(tFtl, null, custLookupCond, false);
             assertEquals(tFtl, t.getName());
             assertEquals(tFtl, t.getSourceName());
             assertEquals(Locale.GERMAN, t.getLocale());
             assertEquals(custLookupCond, t.getCustomLookupCondition());
-            assertEquals(utf8, t.getEncoding());
-            assertOutputEquals("1", t);
-        }
-        {
-            Template t = cfg.getTemplate(tFtl, hu, custLookupCond, null, false);
-            assertEquals(tFtl, t.getName());
-            assertEquals(tFtl, t.getSourceName());
-            assertEquals(hu, t.getLocale());
-            assertEquals(custLookupCond, t.getCustomLookupCondition());
-            assertEquals(latin2, t.getEncoding());
+            assertEquals(latin1, t.getEncoding());
             assertOutputEquals("1", t);
         }
-        try {
-            cfg.getTemplate("missing.ftl", hu, custLookupCond, utf8, false);
-            fail();
-        } catch (TemplateNotFoundException e) {
-            // Expected
-        }
-        assertNull(cfg.getTemplate("missing.ftl", hu, custLookupCond, utf8, true));
     }
 
     private void assertOutputEquals(final String expectedContent, final Template t) throws ConfigurationException,

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f6a693c5/src/test/java/org/apache/freemarker/core/TemplatGetEncodingTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/freemarker/core/TemplatGetEncodingTest.java b/src/test/java/org/apache/freemarker/core/TemplatGetEncodingTest.java
deleted file mode 100644
index 60ba865..0000000
--- a/src/test/java/org/apache/freemarker/core/TemplatGetEncodingTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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 static org.junit.Assert.*;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-
-import org.apache.freemarker.core.templateresolver.ConditionalTemplateConfigurationFactory;
-import org.apache.freemarker.core.templateresolver.FileNameGlobMatcher;
-import org.apache.freemarker.core.templateresolver.impl.ByteArrayTemplateLoader;
-import org.apache.freemarker.core.templateresolver.impl.StrongCacheStorage;
-import org.junit.Test;
-
-public class TemplatGetEncodingTest {
-
-    @Test
-    public void test() throws IOException {
-        Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
-        {
-            cfg.setDefaultEncoding("ISO-8859-2");
-            ByteArrayTemplateLoader tl = new ByteArrayTemplateLoader();
-            tl.putTemplate("t", "test".getBytes(StandardCharsets.UTF_8));
-            tl.putTemplate("static", "<#test>".getBytes(StandardCharsets.UTF_8));
-            TemplateConfiguration staticTextTC = new TemplateConfiguration();
-            staticTextTC.setTemplateLanguage(TemplateLanguage.STATIC_TEXT);
-            cfg.setTemplateConfigurations(
-                    new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("static"), staticTextTC));
-            cfg.setTemplateLoader(tl);
-            cfg.setCacheStorage(new StrongCacheStorage());
-        }
-
-        {
-            Template tDefEnc = cfg.getTemplate("t");
-            assertEquals("ISO-8859-2", tDefEnc.getEncoding());
-            assertSame(tDefEnc, cfg.getTemplate("t"));
-
-            Template tDefEnc2 = cfg.getTemplate("t", (String) null);
-            assertEquals("ISO-8859-2", tDefEnc2.getEncoding());
-            assertSame(tDefEnc, tDefEnc2);
-            
-            Template tUTF8 = cfg.getTemplate("t", "UTF-8");
-            assertEquals("UTF-8", tUTF8.getEncoding());
-            assertSame(tUTF8, cfg.getTemplate("t", "UTF-8"));
-            assertNotSame(tDefEnc, tUTF8);
-        }
-
-        {
-            Template tDefEnc = cfg.getTemplate("static", null, null, false);
-            assertEquals("ISO-8859-2", tDefEnc.getEncoding());
-            assertSame(tDefEnc, cfg.getTemplate("static", null, null, false));
-
-            Template tUTF8 = cfg.getTemplate("static", null, "UTF-8", false);
-            assertEquals("UTF-8", tUTF8.getEncoding());
-            assertSame(tUTF8, cfg.getTemplate("static", null, "UTF-8", false));
-            assertNotSame(tDefEnc, tUTF8);
-        }
-        
-        {
-            Template nonStoredT = new Template(null, "test", cfg);
-            assertNull(nonStoredT.getEncoding());
-        }
-
-        {
-            Template nonStoredT = Template.createPlainTextTemplate(null, "<#test>", cfg);
-            assertNull(nonStoredT.getEncoding());
-        }
-    }
-
-}