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 2018/04/14 14:02:28 UTC

[1/2] freemarker git commit: Continued work on TemplateLanguage configuration and new file extensions: Banned *.ftl* by default (with error message saying that FM2 templates aren't supported in FM3). Also improved UnparsedTemplateLanguage a bit.

Repository: freemarker
Updated Branches:
  refs/heads/3 7a3c48172 -> a89a67713


Continued work on TemplateLanguage configuration and new file extensions: Banned *.ftl* by default (with error message saying that FM2 templates aren't supported in FM3). Also improved UnparsedTemplateLanguage a bit.


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

Branch: refs/heads/3
Commit: 4b5422e0180db58a3dd52c49eccb531e3c6f6e20
Parents: 7a3c481
Author: ddekany <dd...@apache.org>
Authored: Fri Apr 13 17:46:46 2018 +0200
Committer: ddekany <dd...@apache.org>
Committed: Fri Apr 13 17:47:20 2018 +0200

----------------------------------------------------------------------
 FM3-CHANGE-LOG.txt                              |  3 +-
 .../core/TemplateConfigurationTest.java         |  4 +-
 .../core/TemplateGetEncodingTest.java           |  2 +-
 .../freemarker/core/TemplateLanguageTest.java   | 73 +++++++++++++++++++-
 .../apache/freemarker/core/Configuration.java   | 11 +--
 ...utableParsingAndProcessingConfiguration.java |  2 +-
 .../core/UnparsedTemplateLanguage.java          | 15 +++-
 .../core/UnsupportedFM2TemplateLanguage.java    | 63 +++++++++++++++++
 8 files changed, 160 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/freemarker/blob/4b5422e0/FM3-CHANGE-LOG.txt
----------------------------------------------------------------------
diff --git a/FM3-CHANGE-LOG.txt b/FM3-CHANGE-LOG.txt
index b849d9a..c30b690 100644
--- a/FM3-CHANGE-LOG.txt
+++ b/FM3-CHANGE-LOG.txt
@@ -253,7 +253,8 @@ Major changes / features
      the `Configuration` or other kind of `ParsingConfiguration`). This is important for syntax highlighting of the
      static parts, hence it's encoded into the file extension too. It's also important for security reasons, 
   So a common file extensions will be "f3ah".
-  The FM2 file extensions, "ftl", "ftlh", and "ftlx" are banned to prevent confusion [TODO: not yet...].
+  The FM2 file extensions, "ftl", "ftlh", and "ftlx" by default give error (FM 2 templates not supported) to
+  prevent confusion.
   
 
 Smaller Java API changes (categorized)

http://git-wip-us.apache.org/repos/asf/freemarker/blob/4b5422e0/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateConfigurationTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateConfigurationTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateConfigurationTest.java
index fdd699c..145e347 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateConfigurationTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateConfigurationTest.java
@@ -190,7 +190,7 @@ public class TemplateConfigurationTest {
                 ImmutableMap.of("dummy", EpochMillisTemplateDateFormatFactory.INSTANCE));
 
         // Parser-only settings:
-        SETTING_ASSIGNMENTS.put("templateLanguage", UnparsedTemplateLanguage.INSTANCE);
+        SETTING_ASSIGNMENTS.put("templateLanguage", UnparsedTemplateLanguage.F3UU);
         SETTING_ASSIGNMENTS.put("tagSyntax", TagSyntax.SQUARE_BRACKET);
         SETTING_ASSIGNMENTS.put("interpolationSyntax", InterpolationSyntax.SQUARE_BRACKET);
         SETTING_ASSIGNMENTS.put("whitespaceStripping", false);
@@ -621,7 +621,7 @@ public class TemplateConfigurationTest {
             // assertOutput here, as that hard-coded to create an FTL Template.
 
             TemplateConfiguration.Builder tcb = new TemplateConfiguration.Builder();
-            tcb.setTemplateLanguage(UnparsedTemplateLanguage.INSTANCE);
+            tcb.setTemplateLanguage(UnparsedTemplateLanguage.F3UU);
 
             TestConfigurationBuilder cfgB = new TestConfigurationBuilder();
             cfgB.setTemplateConfigurations(

http://git-wip-us.apache.org/repos/asf/freemarker/blob/4b5422e0/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateGetEncodingTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateGetEncodingTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateGetEncodingTest.java
index 0c16fe6..8e993b9 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateGetEncodingTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateGetEncodingTest.java
@@ -44,7 +44,7 @@ public class TemplateGetEncodingTest {
             tl.putTextTemplate("text", "test");
             tl.putTextTemplate("text-static", "<#test>");
             TemplateConfiguration.Builder staticTextTCB = new TemplateConfiguration.Builder();
-            staticTextTCB.setTemplateLanguage(UnparsedTemplateLanguage.INSTANCE);
+            staticTextTCB.setTemplateLanguage(UnparsedTemplateLanguage.F3UU);
             cfgB.setTemplateConfigurations(
                     new ConditionalTemplateConfigurationFactory(
                             new FileNameGlobMatcher("*-static*"), staticTextTCB.build()));

http://git-wip-us.apache.org/repos/asf/freemarker/blob/4b5422e0/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateLanguageTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateLanguageTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateLanguageTest.java
index 211dec1..47026d3 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateLanguageTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateLanguageTest.java
@@ -19,6 +19,7 @@
 
 package org.apache.freemarker.core;
 
+import static org.hamcrest.Matchers.*;
 import static org.junit.Assert.*;
 
 import java.io.IOException;
@@ -26,12 +27,17 @@ import java.io.InputStream;
 import java.io.Reader;
 
 import org.apache.freemarker.core.outputformat.OutputFormat;
+import org.apache.freemarker.core.outputformat.impl.HTMLOutputFormat;
+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.test.TestConfigurationBuilder;
 import org.junit.Test;
 
 public class TemplateLanguageTest {
     
     @Test
-    public void fileExtensionRestrictionsTest() {
+    public void testFileExtensionRestrictions() {
         new DummyTemplateLanguage("xfoo", null, null);
         
         new DummyTemplateLanguage("ffoo", true, null, null);
@@ -82,5 +88,70 @@ public class TemplateLanguageTest {
         }
         
     }
+    
+    @Test
+    public void testDefaultFileExtensionsRecognized() throws Exception {
+        Configuration cfg = new TestConfigurationBuilder()
+                .outputFormat(RTFOutputFormat.INSTANCE)
+                .build();
+        
+        assertLanguageAndOutputFormat(
+                new Template("foo.f3ac", "", cfg),
+                DefaultTemplateLanguage.F3AC, RTFOutputFormat.INSTANCE);
+        assertLanguageAndOutputFormat(
+                new Template("foo.notRecognized", "", cfg),
+                DefaultTemplateLanguage.F3AC, RTFOutputFormat.INSTANCE);
+        assertLanguageAndOutputFormat(
+                new Template("foo.f3au", "", cfg),
+                DefaultTemplateLanguage.F3AU, UndefinedOutputFormat.INSTANCE);
+        assertLanguageAndOutputFormat(
+                new Template("foo.f3ah", "", cfg),
+                DefaultTemplateLanguage.F3AH, HTMLOutputFormat.INSTANCE);
+        assertLanguageAndOutputFormat(
+                new Template("foo.f3ax", "", cfg),
+                DefaultTemplateLanguage.F3AX, XMLOutputFormat.INSTANCE);
+        
+        assertLanguageAndOutputFormat(
+                new Template("foo.f3sc", "", cfg),
+                DefaultTemplateLanguage.F3SC, RTFOutputFormat.INSTANCE);
+        assertLanguageAndOutputFormat(
+                new Template("foo.f3su", "", cfg),
+                DefaultTemplateLanguage.F3SU, UndefinedOutputFormat.INSTANCE);
+        assertLanguageAndOutputFormat(
+                new Template("foo.f3sh", "", cfg),
+                DefaultTemplateLanguage.F3SH, HTMLOutputFormat.INSTANCE);
+        assertLanguageAndOutputFormat(
+                new Template("foo.f3sx", "", cfg),
+                DefaultTemplateLanguage.F3SX, XMLOutputFormat.INSTANCE);
+        
+        assertLanguageAndOutputFormat(
+                new Template("foo.f3uu", "", cfg),
+                UnparsedTemplateLanguage.F3UU, UndefinedOutputFormat.INSTANCE);
+        
+       try {
+           new Template("foo.ftl", "", cfg);
+           fail();
+       } catch (ParseException e) {
+           assertThat(e.getMessage(), allOf(containsString("FreeMarker 2"), containsString("*.ftl")));
+       }
+       try {
+           new Template("foo.ftlh", "", cfg);
+           fail();
+       } catch (ParseException e) {
+           assertThat(e.getMessage(), allOf(containsString("FreeMarker 2"), containsString("*.ftlh")));
+       }
+       try {
+           new Template("foo.ftlx", "", cfg);
+           fail();
+       } catch (ParseException e) {
+           assertThat(e.getMessage(), allOf(containsString("FreeMarker 2"), containsString("*.ftlx")));
+       }
+    }
+
+    private void assertLanguageAndOutputFormat(Template template, TemplateLanguage expectedLanguage,
+            OutputFormat expectedOutputFromat) {
+        assertEquals(expectedLanguage, template.getParsingConfiguration().getTemplateLanguage());
+        assertEquals(expectedOutputFromat, template.getOutputFormat());
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/freemarker/blob/4b5422e0/freemarker-core/src/main/java/org/apache/freemarker/core/Configuration.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/Configuration.java b/freemarker-core/src/main/java/org/apache/freemarker/core/Configuration.java
index 60c372a..be9f802 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/Configuration.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/Configuration.java
@@ -762,13 +762,16 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
     
     static final Map<String, TemplateLanguage> PREDEFINED_TEMPLATE_LANGUAGES_BY_EXTENSION;
     static {
-        PREDEFINED_TEMPLATE_LANGUAGES_BY_EXTENSION = new HashMap<String, TemplateLanguage>(
-                (DefaultTemplateLanguage.STANDARD_INSTANCES.length + 1) * 2, 0.5f);
-        for (DefaultTemplateLanguage tl : DefaultTemplateLanguage.STANDARD_INSTANCES) {
+        PREDEFINED_TEMPLATE_LANGUAGES_BY_EXTENSION = new HashMap<String, TemplateLanguage>(32);
+        
+        for (TemplateLanguage tl : DefaultTemplateLanguage.STANDARD_INSTANCES) {
+            PREDEFINED_TEMPLATE_LANGUAGES_BY_EXTENSION.put(tl.getFileExtension(), tl);            
+        }
+        for (TemplateLanguage tl : UnsupportedFM2TemplateLanguage.INSTANCES) {
             PREDEFINED_TEMPLATE_LANGUAGES_BY_EXTENSION.put(tl.getFileExtension(), tl);            
         }
         PREDEFINED_TEMPLATE_LANGUAGES_BY_EXTENSION.put(
-                UnparsedTemplateLanguage.INSTANCE.getFileExtension(), UnparsedTemplateLanguage.INSTANCE);            
+                UnparsedTemplateLanguage.F3UU.getFileExtension(), UnparsedTemplateLanguage.F3UU);            
     }
     
     /**

http://git-wip-us.apache.org/repos/asf/freemarker/blob/4b5422e0/freemarker-core/src/main/java/org/apache/freemarker/core/MutableParsingAndProcessingConfiguration.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/MutableParsingAndProcessingConfiguration.java b/freemarker-core/src/main/java/org/apache/freemarker/core/MutableParsingAndProcessingConfiguration.java
index 5bcb652..0f6b83e 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/MutableParsingAndProcessingConfiguration.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/MutableParsingAndProcessingConfiguration.java
@@ -117,7 +117,7 @@ public abstract class MutableParsingAndProcessingConfiguration<
                         value.toLowerCase());
                 if (templateLanguage == null) {
                     if ("staticText".equals(value)) {
-                        templateLanguage = UnparsedTemplateLanguage.INSTANCE;
+                        templateLanguage = UnparsedTemplateLanguage.F3UU;
                     } else {
                         // TODO [FM3] Allow setting a custom template language by class name.
                         throw new InvalidSettingValueException(name, value, "Unsupported template language name");

http://git-wip-us.apache.org/repos/asf/freemarker/blob/4b5422e0/freemarker-core/src/main/java/org/apache/freemarker/core/UnparsedTemplateLanguage.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/UnparsedTemplateLanguage.java b/freemarker-core/src/main/java/org/apache/freemarker/core/UnparsedTemplateLanguage.java
index 430bda7..b2b9834 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/UnparsedTemplateLanguage.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/UnparsedTemplateLanguage.java
@@ -33,10 +33,13 @@ public final class UnparsedTemplateLanguage extends TemplateLanguage {
     
     private static final int READ_BUFFER_SIZE = 4096;
     
-    public static final TemplateLanguage INSTANCE = new UnparsedTemplateLanguage();
+    /**
+     * Instance with {@link UndefinedOutputFormat} output format. 
+     */
+    public static final UnparsedTemplateLanguage F3UU = new UnparsedTemplateLanguage(UndefinedOutputFormat.INSTANCE);
 
-    private UnparsedTemplateLanguage() {
-        super("f3uu", true, UndefinedOutputFormat.INSTANCE, AutoEscapingPolicy.ENABLE_IF_DEFAULT);
+    private UnparsedTemplateLanguage(OutputFormat outputFormat) {
+        super("f3uu", true, outputFormat, AutoEscapingPolicy.ENABLE_IF_DEFAULT);
     }
 
     /**
@@ -63,6 +66,12 @@ public final class UnparsedTemplateLanguage extends TemplateLanguage {
         ASTStaticText root = new ASTStaticText(sb.toString());
         root.setFieldsForRootElement();
         root.setLocation(template, -1, -1, -1, -1); // TODO [FM3] Positions are dummy
+        
+        template.setOutputFormat(contextOutputFormat != null ? contextOutputFormat
+                : getOutputFormat(template.getConfiguration()));
+        template.setAutoEscapingPolicy(contextAutoEscapingPolicy != null ? contextAutoEscapingPolicy
+                : getAutoEscapingPolicy());
+        
         return root;
     }
     

http://git-wip-us.apache.org/repos/asf/freemarker/blob/4b5422e0/freemarker-core/src/main/java/org/apache/freemarker/core/UnsupportedFM2TemplateLanguage.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/UnsupportedFM2TemplateLanguage.java b/freemarker-core/src/main/java/org/apache/freemarker/core/UnsupportedFM2TemplateLanguage.java
new file mode 100644
index 0000000..0170f36
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/UnsupportedFM2TemplateLanguage.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.core;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+import org.apache.freemarker.core.outputformat.OutputFormat;
+
+/**
+ * FreeMarker 2 template language, which we don't support. To avoid confusion we ban loading such templates. 
+ */
+class UnsupportedFM2TemplateLanguage extends TemplateLanguage {
+
+    private static final UnsupportedFM2TemplateLanguage FTL = new UnsupportedFM2TemplateLanguage(
+            "ftl", null, AutoEscapingPolicy.ENABLE_IF_DEFAULT);  
+    private static final UnsupportedFM2TemplateLanguage FTLH = new UnsupportedFM2TemplateLanguage(
+            "ftlh", null, AutoEscapingPolicy.ENABLE_IF_DEFAULT);  
+    private static final UnsupportedFM2TemplateLanguage FTLX = new UnsupportedFM2TemplateLanguage(
+            "ftlx", null, AutoEscapingPolicy.ENABLE_IF_DEFAULT);
+    
+    static final UnsupportedFM2TemplateLanguage[] INSTANCES = new UnsupportedFM2TemplateLanguage[] { FTL, FTLH, FTLX };
+    
+    private UnsupportedFM2TemplateLanguage(String fileExtension, OutputFormat outputFormat,
+            AutoEscapingPolicy autoEscapingPolicy) {
+        super(fileExtension, true, outputFormat, autoEscapingPolicy);
+    }
+
+    @Override
+    public boolean getCanSpecifyEncodingInContent() {
+        return false;
+    }
+
+    @Override
+    public ASTElement parse(Template template, Reader reader, ParsingConfiguration pCfg,
+            OutputFormat contextOutputFormat, AutoEscapingPolicy contextAutoEscapingPolicy,
+            InputStream streamToUnmarkWhenEncEstabd) throws IOException, ParseException {
+        throw new ParseException(
+                "FreeMarker 2 templates (*." + getFileExtension() + ") aren't supported in FreeMarker 3. "
+                + "(Note that FreeMarker 2 and 3 uses different Java packages, so you can use both in the same "
+                + "application.)",
+                template, 0, 0, 0, 0);
+    }
+
+}


[2/2] freemarker git commit: Cleaned up the treatment of outputFormat-s and autoEscapingPolicy, so that complicated part is done inside Template, not in the TemplateLanguage implementation.

Posted by dd...@apache.org.
Cleaned up the treatment of outputFormat-s and autoEscapingPolicy, so that complicated part is done inside Template, not in the TemplateLanguage implementation.


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

Branch: refs/heads/3
Commit: a89a67713dcc5386a38a808497e09e7856beb3c6
Parents: 4b5422e
Author: ddekany <dd...@apache.org>
Authored: Sat Apr 14 16:01:52 2018 +0200
Committer: ddekany <dd...@apache.org>
Committed: Sat Apr 14 16:01:52 2018 +0200

----------------------------------------------------------------------
 .../freemarker/core/TemplateLanguageTest.java   |   1 -
 .../freemarker/core/ASTExpStringLiteral.java    |   2 +-
 .../freemarker/core/BuiltInsForStringsMisc.java |  21 ++-
 .../core/DefaultTemplateLanguage.java           |   4 +-
 .../core/FinalParsingConfiguration.java         | 169 +++++++++++++++++++
 .../core/OutputFormatBoundBuiltIn.java          |   5 +
 ...nfigurationWithTemplateLanguageOverride.java | 131 --------------
 .../org/apache/freemarker/core/Template.java    |  42 +++--
 .../freemarker/core/TemplateLanguage.java       |   9 +-
 .../core/UnparsedTemplateLanguage.java          |   7 +-
 .../core/UnsupportedFM2TemplateLanguage.java    |   1 -
 freemarker-core/src/main/javacc/FTL.jj          |  32 +---
 12 files changed, 225 insertions(+), 199 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/freemarker/blob/a89a6771/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateLanguageTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateLanguageTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateLanguageTest.java
index 47026d3..069394b 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateLanguageTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateLanguageTest.java
@@ -82,7 +82,6 @@ public class TemplateLanguageTest {
 
         @Override
         public ASTElement parse(Template template, Reader reader, ParsingConfiguration pCfg,
-                OutputFormat contextOutputFormat, AutoEscapingPolicy contextAutoEscapingPolicy,
                 InputStream streamToUnmarkWhenEncEstabd) throws IOException, ParseException {
             throw new RuntimeException("Not implemented");
         }

http://git-wip-us.apache.org/repos/asf/freemarker/blob/a89a6771/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpStringLiteral.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpStringLiteral.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpStringLiteral.java
index 3e1745f..c20de82 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpStringLiteral.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpStringLiteral.java
@@ -71,7 +71,7 @@ final class ASTExpStringLiteral extends ASTExpression implements TemplateStringM
                         simpleCharacterStream);
                 
                 FMParser parser = new FMParser(parentTemplate, false,
-                        tkMan, pCfg, null, null,
+                        tkMan, pCfg,
                         null);
                 // We continue from the parent parser's current state:
                 parser.setupStringLiteralMode(parentTkMan, outputFormat);

http://git-wip-us.apache.org/repos/asf/freemarker/blob/a89a6771/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java b/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java
index f062612..e956859 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java
@@ -35,6 +35,7 @@ import org.apache.freemarker.core.model.impl.BeanModel;
 import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
 import org.apache.freemarker.core.model.impl.SimpleNumber;
 import org.apache.freemarker.core.model.impl.SimpleString;
+import org.apache.freemarker.core.outputformat.OutputFormat;
 import org.apache.freemarker.core.templateresolver.MalformedTemplateNameException;
 import org.apache.freemarker.core.util.CallableUtils;
 
@@ -65,19 +66,31 @@ class BuiltInsForStringsMisc {
 
     static class evalBI extends OutputFormatBoundBuiltIn {
         
+        private ParsingConfiguration pCfg;
+        
         @Override
         protected TemplateModel calculateResult(Environment env) throws TemplateException {
             return calculateResult(BuiltInForString.getTargetString(target, env), env);
         }
         
+        @Override
+        void bindToOutputFormat(OutputFormat outputFormat, AutoEscapingPolicy autoEscapingPolicy) {
+            super.bindToOutputFormat(outputFormat, autoEscapingPolicy);
+            Template template = getTemplate();
+            ParsingConfiguration pCfg = template.getParsingConfiguration();
+            if (pCfg.getOutputFormat() != outputFormat || pCfg.getAutoEscapingPolicy() != autoEscapingPolicy) {
+                pCfg = new FinalParsingConfiguration(pCfg, pCfg.getTemplateLanguage(), outputFormat, autoEscapingPolicy,
+                        template.getConfiguration());
+            }
+            this.pCfg = pCfg; 
+        }
+
         TemplateModel calculateResult(String s, Environment env) throws TemplateException {
             Template parentTemplate = getTemplate();
             
             ASTExpression exp;
             try {
                 try {
-                    ParsingConfiguration pCfg = parentTemplate.getParsingConfiguration();
-                    
                     SimpleCharStream simpleCharStream = new SimpleCharStream(
                             new StringReader("(" + s + ")"),
                             RUNTIME_EVAL_LINE_DISPLACEMENT, 1,
@@ -90,7 +103,7 @@ class BuiltInsForStringsMisc {
                     // pCfg.outputFormat+autoEscapingPolicy is exceptional: it's inherited from the lexical context
                     FMParser parser = new FMParser(
                             parentTemplate, false, tkMan,
-                            pCfg, outputFormat, autoEscapingPolicy,
+                            pCfg,
                             null);
                     
                     exp = parser.Expression();
@@ -260,10 +273,8 @@ class BuiltInsForStringsMisc {
         class ConstructorFunction extends BuiltInCallableImpl implements TemplateFunctionModel {
 
             private final Class<?> cl;
-            private final Environment env;
             
             ConstructorFunction(String classname, Environment env, Template template) throws TemplateException {
-                this.env = env;
                 cl = env.getNewBuiltinClassResolver().resolve(classname, env, template);
                 if (!TemplateModel.class.isAssignableFrom(cl)) {
                     throw new TemplateException(newBI.this, env,

http://git-wip-us.apache.org/repos/asf/freemarker/blob/a89a6771/freemarker-core/src/main/java/org/apache/freemarker/core/DefaultTemplateLanguage.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/DefaultTemplateLanguage.java b/freemarker-core/src/main/java/org/apache/freemarker/core/DefaultTemplateLanguage.java
index 999789d..644ab25 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/DefaultTemplateLanguage.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/DefaultTemplateLanguage.java
@@ -125,14 +125,12 @@ public final class DefaultTemplateLanguage extends TemplateLanguage {
 
     @Override
     public ASTElement parse(Template template, Reader reader,
-            ParsingConfiguration pCfg, OutputFormat contextOutputFormat, AutoEscapingPolicy contextAutoEscapingPolicy,
+            ParsingConfiguration pCfg,
             InputStream streamToUnmarkWhenEncEstabd)
             throws IOException, ParseException {
         FMParser parser = new FMParser(
                 template, reader,
                 pCfg,
-                contextOutputFormat,
-                contextAutoEscapingPolicy,
                 streamToUnmarkWhenEncEstabd);
         ASTElement root = parser.Root();
         template.actualTagSyntax = parser._getLastTagSyntax();

http://git-wip-us.apache.org/repos/asf/freemarker/blob/a89a6771/freemarker-core/src/main/java/org/apache/freemarker/core/FinalParsingConfiguration.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/FinalParsingConfiguration.java b/freemarker-core/src/main/java/org/apache/freemarker/core/FinalParsingConfiguration.java
new file mode 100644
index 0000000..72c9211
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/FinalParsingConfiguration.java
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.core;
+
+import java.nio.charset.Charset;
+
+import org.apache.freemarker.core.arithmetic.ArithmeticEngine;
+import org.apache.freemarker.core.outputformat.OutputFormat;
+
+/**
+ * Used for creating the final {@link ParsingConfiguration} passed to
+ * {@link TemplateLanguage#parse(Template, java.io.Reader, ParsingConfiguration, java.io.InputStream)}.
+ * Overrides the {@link TemplateLanguage} in a {@link ParsingConfiguration}, also the {@link OutputFormat} and/or
+ * {@link AutoEscapingPolicy} if the {@link TemplateLanguage} or the context requires that.
+ */
+final class FinalParsingConfiguration implements ParsingConfiguration {
+
+    private final ParsingConfiguration pCfg;
+    private final TemplateLanguage templateLanguage;
+    private final OutputFormat outputFormat;
+    private final AutoEscapingPolicy autoEscapingPolicy;
+
+    /**
+     * @param pCfg
+     *            The {@link ParsingConfiguration} where we override some settings; not {@code null}
+     * @param templateLanguage
+     *            The final {@link TemplateLanguage} to be used; not {@code null}.
+     * @param contextOutputFormat
+     *            See similar parameter in {@link Template#Template(String, String, java.io.InputStream, Charset,
+     *            java.io.Reader, Configuration, TemplateConfiguration, OutputFormat, AutoEscapingPolicy)};
+     *            maybe {@code null}.
+     * @param contextAutoEscapingPolicy
+     *            See similar parameter in {@link Template#Template(String, String, java.io.InputStream, Charset,
+     *            java.io.Reader, Configuration, TemplateConfiguration, OutputFormat, AutoEscapingPolicy)};
+     *            maybe {@code null}.
+     * @param cfg
+     *            Not {@code null}
+     */
+    FinalParsingConfiguration(
+            ParsingConfiguration pCfg, TemplateLanguage templateLanguage,
+            OutputFormat contextOutputFormat, AutoEscapingPolicy contextAutoEscapingPolicy,
+            Configuration cfg) {
+        this.pCfg = pCfg;
+        this.templateLanguage = templateLanguage;
+
+        // contextXxx is stronger than anything.
+        // TemplateLanguage.xxx (if it's non-null) stronger than the rest.
+        
+        OutputFormat tempLangOutputFormat;
+        this.outputFormat = contextOutputFormat != null ? contextOutputFormat
+                : (tempLangOutputFormat = templateLanguage.getOutputFormat(cfg)) != null
+                        ? tempLangOutputFormat
+                : pCfg.getOutputFormat();
+        
+        AutoEscapingPolicy tempLangAutoEscapingPolicy; 
+        this.autoEscapingPolicy = contextAutoEscapingPolicy != null ? contextAutoEscapingPolicy
+                : (tempLangAutoEscapingPolicy = templateLanguage.getAutoEscapingPolicy()) != null
+                        ? tempLangAutoEscapingPolicy
+                : pCfg.getAutoEscapingPolicy();
+    }
+
+    @Override
+    public TemplateLanguage getTemplateLanguage() {
+        return templateLanguage;
+    }
+
+    @Override
+    public boolean isTemplateLanguageSet() {
+        return true;
+    }
+
+    @Override
+    public boolean getWhitespaceStripping() {
+        return pCfg.getWhitespaceStripping();
+    }
+
+    @Override
+    public boolean isWhitespaceStrippingSet() {
+        return pCfg.isWhitespaceStrippingSet();
+    }
+
+    @Override
+    public ArithmeticEngine getArithmeticEngine() {
+        return pCfg.getArithmeticEngine();
+    }
+
+    @Override
+    public boolean isArithmeticEngineSet() {
+        return pCfg.isArithmeticEngineSet();
+    }
+
+    @Override
+    public AutoEscapingPolicy getAutoEscapingPolicy() {
+        return autoEscapingPolicy;
+    }
+
+    @Override
+    public boolean isAutoEscapingPolicySet() {
+        return autoEscapingPolicy != null;
+    }
+
+    @Override
+    public OutputFormat getOutputFormat() {
+        return outputFormat;
+    }
+
+    @Override
+    public boolean isOutputFormatSet() {
+        return outputFormat != null;
+    }
+
+    @Override
+    public boolean getRecognizeStandardFileExtensions() {
+        return pCfg.getRecognizeStandardFileExtensions();
+    }
+
+    @Override
+    public boolean isRecognizeStandardFileExtensionsSet() {
+        return pCfg.isRecognizeStandardFileExtensionsSet();
+    }
+
+    @Override
+    public Version getIncompatibleImprovements() {
+        return pCfg.getIncompatibleImprovements();
+    }
+
+    @Override
+    public boolean isIncompatibleImprovementsSet() {
+        return pCfg.isIncompatibleImprovementsSet();
+    }
+
+    @Override
+    public int getTabSize() {
+        return pCfg.getTabSize();
+    }
+
+    @Override
+    public boolean isTabSizeSet() {
+        return pCfg.isTabSizeSet();
+    }
+
+    @Override
+    public Charset getSourceEncoding() {
+        return pCfg.getSourceEncoding();
+    }
+
+    @Override
+    public boolean isSourceEncodingSet() {
+        return pCfg.isSourceEncodingSet();
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/freemarker/blob/a89a6771/freemarker-core/src/main/java/org/apache/freemarker/core/OutputFormatBoundBuiltIn.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/OutputFormatBoundBuiltIn.java b/freemarker-core/src/main/java/org/apache/freemarker/core/OutputFormatBoundBuiltIn.java
index 4193ca6..b535003 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/OutputFormatBoundBuiltIn.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/OutputFormatBoundBuiltIn.java
@@ -27,6 +27,11 @@ abstract class OutputFormatBoundBuiltIn extends SpecialBuiltIn {
     protected OutputFormat outputFormat;
     protected AutoEscapingPolicy autoEscapingPolicy;
     
+    /**
+     * Binds the {@link ASTNode} to the output format and auto-escaping context of its lexical context.
+     * Called when the {@link ASTNode} location was already set (so {@link #getTemplate()} will return
+     * non-{@code null}).
+     */
     void bindToOutputFormat(OutputFormat outputFormat, AutoEscapingPolicy autoEscapingPolicy) {
         _NullArgumentException.check(outputFormat);
         this.outputFormat = outputFormat;

http://git-wip-us.apache.org/repos/asf/freemarker/blob/a89a6771/freemarker-core/src/main/java/org/apache/freemarker/core/ParsingConfigurationWithTemplateLanguageOverride.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ParsingConfigurationWithTemplateLanguageOverride.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ParsingConfigurationWithTemplateLanguageOverride.java
deleted file mode 100644
index b6b3c09..0000000
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ParsingConfigurationWithTemplateLanguageOverride.java
+++ /dev/null
@@ -1,131 +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 java.nio.charset.Charset;
-
-import org.apache.freemarker.core.arithmetic.ArithmeticEngine;
-import org.apache.freemarker.core.outputformat.OutputFormat;
-
-/**
- * Used when the {@link TemplateLanguage} in the {@link ParsingConfiguration} need to be replaced.
- */
-final class ParsingConfigurationWithTemplateLanguageOverride implements ParsingConfiguration {
-
-    private final ParsingConfiguration pCfg;
-    private final TemplateLanguage templateLanguage;
-    
-    public ParsingConfigurationWithTemplateLanguageOverride(ParsingConfiguration pCfg,
-            TemplateLanguage templateLanguage) {
-        this.pCfg = pCfg;
-        this.templateLanguage = templateLanguage;
-    }
-
-    @Override
-    public TemplateLanguage getTemplateLanguage() {
-        return templateLanguage;
-    }
-
-    @Override
-    public boolean isTemplateLanguageSet() {
-        return true;
-    }
-
-    @Override
-    public boolean getWhitespaceStripping() {
-        return pCfg.getWhitespaceStripping();
-    }
-
-    @Override
-    public boolean isWhitespaceStrippingSet() {
-        return pCfg.isWhitespaceStrippingSet();
-    }
-
-    @Override
-    public ArithmeticEngine getArithmeticEngine() {
-        return pCfg.getArithmeticEngine();
-    }
-
-    @Override
-    public boolean isArithmeticEngineSet() {
-        return pCfg.isArithmeticEngineSet();
-    }
-
-    @Override
-    public AutoEscapingPolicy getAutoEscapingPolicy() {
-        return pCfg.getAutoEscapingPolicy();
-    }
-
-    @Override
-    public boolean isAutoEscapingPolicySet() {
-        return pCfg.isAutoEscapingPolicySet();
-    }
-
-    @Override
-    public OutputFormat getOutputFormat() {
-        return pCfg.getOutputFormat();
-    }
-
-    @Override
-    public boolean isOutputFormatSet() {
-        return pCfg.isOutputFormatSet();
-    }
-
-    @Override
-    public boolean getRecognizeStandardFileExtensions() {
-        return pCfg.getRecognizeStandardFileExtensions();
-    }
-
-    @Override
-    public boolean isRecognizeStandardFileExtensionsSet() {
-        return pCfg.isRecognizeStandardFileExtensionsSet();
-    }
-
-    @Override
-    public Version getIncompatibleImprovements() {
-        return pCfg.getIncompatibleImprovements();
-    }
-
-    @Override
-    public boolean isIncompatibleImprovementsSet() {
-        return pCfg.isIncompatibleImprovementsSet();
-    }
-
-    @Override
-    public int getTabSize() {
-        return pCfg.getTabSize();
-    }
-
-    @Override
-    public boolean isTabSizeSet() {
-        return pCfg.isTabSizeSet();
-    }
-
-    @Override
-    public Charset getSourceEncoding() {
-        return pCfg.getSourceEncoding();
-    }
-
-    @Override
-    public boolean isSourceEncodingSet() {
-        return pCfg.isSourceEncodingSet();
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/freemarker/blob/a89a6771/freemarker-core/src/main/java/org/apache/freemarker/core/Template.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/Template.java b/freemarker-core/src/main/java/org/apache/freemarker/core/Template.java
index 0907541..c3df6c1 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/Template.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/Template.java
@@ -310,18 +310,23 @@ public class Template implements ProcessingConfiguration, CustomStateScope {
         {
             ParsingConfiguration pCfgWithFallback = tCfg != null
                     ? new ParsingConfigurationWithFallback(tCfg, cfg) : cfg;
-            
-            TemplateLanguage tempLangFromPCfg = pCfgWithFallback.getTemplateLanguage();
-            TemplateLanguage tempLangFromExt = pCfgWithFallback.getRecognizeStandardFileExtensions()
-                    ? configuration.getTemplateLanguageForTemplateName(sourceName != null ? sourceName : lookupName)
-                    : null;
-            if (tempLangFromExt != null && tempLangFromExt != tempLangFromPCfg) {
-                this.pCfg = new ParsingConfigurationWithTemplateLanguageOverride(pCfgWithFallback, tempLangFromExt);
-            } else {
-                this.pCfg = pCfgWithFallback;
-            }
+            TemplateLanguage tempLangFromExt;
+            this.pCfg = new FinalParsingConfiguration(
+                    pCfgWithFallback,
+                    pCfgWithFallback.getRecognizeStandardFileExtensions()
+                            && (tempLangFromExt = configuration.getTemplateLanguageForTemplateName(
+                                    sourceName != null ? sourceName : lookupName)) != null
+                            ? tempLangFromExt
+                            : pCfgWithFallback.getTemplateLanguage(),
+                    contextOutputFormat, contextAutoEscapingPolicy,
+                    cfg);
         }
         
+        // The template can change these with some header directive, so they are stored in the Template as well, not
+        // only in the ParsingConfiguration:
+        setOutputFormat(pCfg.getOutputFormat());
+        setAutoEscapingPolicy(pCfg.getAutoEscapingPolicy());
+        
         this.lookupName = lookupName;
         this.sourceName = sourceName;
         
@@ -357,10 +362,7 @@ public class Template implements ProcessingConfiguration, CustomStateScope {
 
         try {
             try {
-                parseWithEncoding(
-                        reader,
-                        contextOutputFormat, contextAutoEscapingPolicy,
-                        guessedEncoding, inputStreamMarked ? inputStream : null);
+                parseWithEncoding(reader, guessedEncoding, inputStreamMarked ? inputStream : null);
             } catch (WrongTemplateCharsetException charsetException) {
                 final Charset templateSpecifiedEncoding = charsetException.getTemplateSpecifiedEncoding();
 
@@ -374,10 +376,7 @@ public class Template implements ProcessingConfiguration, CustomStateScope {
                     // We can't handle it, the caller should.
                     throw charsetException;
                 }
-                parseWithEncoding(
-                        reader,
-                        contextOutputFormat, contextAutoEscapingPolicy,
-                        templateSpecifiedEncoding, inputStream);
+                parseWithEncoding(reader, templateSpecifiedEncoding, inputStream);
             }
         } finally {
             if (closeReader) {
@@ -401,7 +400,7 @@ public class Template implements ProcessingConfiguration, CustomStateScope {
      *            mark (so we don't buffer unnecessarily). Maybe {@code null}.
      */
     private void parseWithEncoding(
-            Reader reader, OutputFormat contextOutputFormat, AutoEscapingPolicy contextAutoEscapingPolicy,
+            Reader reader,
             Charset attemptedCharset, InputStream streamToUnmarkWhenEncEstabd) throws ParseException, IOException {
         setActualSourceEncoding(attemptedCharset);
         LineTableBuilder ltbReader;
@@ -418,10 +417,7 @@ public class Template implements ProcessingConfiguration, CustomStateScope {
             
             try {
                 try {
-                    rootElement = pCfg.getTemplateLanguage().parse(
-                            this, reader,
-                            pCfg, contextOutputFormat, contextAutoEscapingPolicy,
-                            streamToUnmarkWhenEncEstabd);
+                    rootElement = pCfg.getTemplateLanguage().parse(this, reader, pCfg, streamToUnmarkWhenEncEstabd);
                 } catch (IndexOutOfBoundsException exc) {
                     // There's a JavaCC bug where the Reader throws a RuntimeExcepton and then JavaCC fails with
                     // IndexOutOfBoundsException. If that wasn't the case, we just rethrow. Otherwise we suppress the

http://git-wip-us.apache.org/repos/asf/freemarker/blob/a89a6771/freemarker-core/src/main/java/org/apache/freemarker/core/TemplateLanguage.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/TemplateLanguage.java b/freemarker-core/src/main/java/org/apache/freemarker/core/TemplateLanguage.java
index 08949b4..3b1a812 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/TemplateLanguage.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/TemplateLanguage.java
@@ -102,10 +102,17 @@ public abstract class TemplateLanguage {
      * This is what
      * {@link Template#Template(String, String, InputStream, Charset, Reader, Configuration, TemplateConfiguration,
      * OutputFormat, AutoEscapingPolicy)} calls internally to do the actual parsing.
+     * 
+     * @param template
+     *            The {@link Template} for which AST (Abstract Syntax Tree) needs to be built.
+     * 
+     * @param pCfg
+     *            Contains the final {@link ParsingConfiguration}; overrides from the {@link TemplateLanguage} are
+     *            already applied to this.
      */
     // TODO [FM3] This is not the final API, or else it can't be public (because ASTElement isn't public for example).
     public abstract ASTElement parse(Template template, Reader reader,
-            ParsingConfiguration pCfg, OutputFormat contextOutputFormat, AutoEscapingPolicy contextAutoEscapingPolicy,
+            ParsingConfiguration pCfg,
             InputStream streamToUnmarkWhenEncEstabd)
             throws IOException, ParseException;
 

http://git-wip-us.apache.org/repos/asf/freemarker/blob/a89a6771/freemarker-core/src/main/java/org/apache/freemarker/core/UnparsedTemplateLanguage.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/UnparsedTemplateLanguage.java b/freemarker-core/src/main/java/org/apache/freemarker/core/UnparsedTemplateLanguage.java
index b2b9834..0af1cbd 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/UnparsedTemplateLanguage.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/UnparsedTemplateLanguage.java
@@ -54,7 +54,7 @@ public final class UnparsedTemplateLanguage extends TemplateLanguage {
 
     @Override
     public ASTElement parse(Template template, Reader reader,
-            ParsingConfiguration pCfg, OutputFormat contextOutputFormat, AutoEscapingPolicy contextAutoEscapingPolicy,
+            ParsingConfiguration pCfg,
             InputStream streamToUnmarkWhenEncEstabd)
             throws IOException, ParseException {
         final StringBuilder sb = new StringBuilder();
@@ -67,11 +67,6 @@ public final class UnparsedTemplateLanguage extends TemplateLanguage {
         root.setFieldsForRootElement();
         root.setLocation(template, -1, -1, -1, -1); // TODO [FM3] Positions are dummy
         
-        template.setOutputFormat(contextOutputFormat != null ? contextOutputFormat
-                : getOutputFormat(template.getConfiguration()));
-        template.setAutoEscapingPolicy(contextAutoEscapingPolicy != null ? contextAutoEscapingPolicy
-                : getAutoEscapingPolicy());
-        
         return root;
     }
     

http://git-wip-us.apache.org/repos/asf/freemarker/blob/a89a6771/freemarker-core/src/main/java/org/apache/freemarker/core/UnsupportedFM2TemplateLanguage.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/UnsupportedFM2TemplateLanguage.java b/freemarker-core/src/main/java/org/apache/freemarker/core/UnsupportedFM2TemplateLanguage.java
index 0170f36..158a35a 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/UnsupportedFM2TemplateLanguage.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/UnsupportedFM2TemplateLanguage.java
@@ -51,7 +51,6 @@ class UnsupportedFM2TemplateLanguage extends TemplateLanguage {
 
     @Override
     public ASTElement parse(Template template, Reader reader, ParsingConfiguration pCfg,
-            OutputFormat contextOutputFormat, AutoEscapingPolicy contextAutoEscapingPolicy,
             InputStream streamToUnmarkWhenEncEstabd) throws IOException, ParseException {
         throw new ParseException(
                 "FreeMarker 2 templates (*." + getFileExtension() + ") aren't supported in FreeMarker 3. "

http://git-wip-us.apache.org/repos/asf/freemarker/blob/a89a6771/freemarker-core/src/main/javacc/FTL.jj
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/javacc/FTL.jj b/freemarker-core/src/main/javacc/FTL.jj
index d4697b3..aff3750 100644
--- a/freemarker-core/src/main/javacc/FTL.jj
+++ b/freemarker-core/src/main/javacc/FTL.jj
@@ -114,10 +114,10 @@ public class FMParser {
     private int topNestedContentParamNamesLength;
 
     FMParser(Template template, Reader reader,
-            ParsingConfiguration pCfg, OutputFormat outputFormat, AutoEscapingPolicy autoEscapingPolicy,
+            ParsingConfiguration pCfg,
             InputStream streamToUnmarkWhenEncEstabd) {
         this(template, true, readerToTokenManager(reader, pCfg),
-                pCfg, outputFormat, autoEscapingPolicy,
+                pCfg,
                 streamToUnmarkWhenEncEstabd);
     }
 
@@ -128,8 +128,7 @@ public class FMParser {
     }
 
     FMParser(Template template, boolean newTemplate, FMParserTokenManager tkMan,
-            ParsingConfiguration pCfg, OutputFormat contextOutputFormat, AutoEscapingPolicy contextAutoEscapingPolicy,
-    		InputStream streamToUnmarkWhenEncEstabd) {
+            ParsingConfiguration pCfg, InputStream streamToUnmarkWhenEncEstabd) {
         this(tkMan);
 
         _NullArgumentException.check(pCfg);
@@ -146,22 +145,8 @@ public class FMParser {
 
         templateLanguage = (DefaultTemplateLanguage) pCfg.getTemplateLanguage();
 
-        {
-            // contextXxx is stronger than anything.
-            // TemplateLanguage.xxx (if it's non-null) stronger than the rest.
-            
-            OutputFormat outputFormatFromLang;
-            outputFormat = contextOutputFormat != null ? contextOutputFormat
-                    : (outputFormatFromLang = templateLanguage.getOutputFormat(template.getConfiguration())) != null
-                            ? outputFormatFromLang
-                            : pCfg.getOutputFormat();
-
-            AutoEscapingPolicy autoEscapingPolicyFromLang;
-            autoEscapingPolicy = contextAutoEscapingPolicy != null ? contextAutoEscapingPolicy
-                    : (autoEscapingPolicyFromLang = templateLanguage.getAutoEscapingPolicy()) != null
-                            ? autoEscapingPolicyFromLang
-                    : pCfg.getAutoEscapingPolicy();
-        }
+        outputFormat = pCfg.getOutputFormat();
+        autoEscapingPolicy = pCfg.getAutoEscapingPolicy();
         recalculateAutoEscapingField();
 
         token_source.setParser(this);
@@ -180,13 +165,6 @@ public class FMParser {
         token_source.interpolationSyntax = templateLanguage.getInterpolationSyntax();
 
         this.stripWhitespace = pCfg.getWhitespaceStripping();
-
-        // If this is a Template under construction, we do the below.
-        // If this is just the enclosing Template for ?eval or such, we must not modify it.
-        if (newTemplate) {
-            template.setAutoEscapingPolicy(autoEscapingPolicy);
-            template.setOutputFormat(outputFormat);
-        }
     }
     
     void setupStringLiteralMode(FMParserTokenManager parentTokenSource, OutputFormat outputFormat) {