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/06/11 17:28:39 UTC

[1/2] incubator-freemarker git commit: Refined setSetting(String, String) and ..._KEY constatns so that they are split between the 3 classes of the inheritance chain: Configuration.ExtendableBuilder, MutableParsingAndProcessingConfiguration, MutableProc

Repository: incubator-freemarker
Updated Branches:
  refs/heads/3 8680c0605 -> a9038a8b9


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/a9038a8b/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 3b96857..2af8ae0 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
@@ -146,49 +146,31 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
     private static final String VERSION_PROPERTIES_PATH = "org/apache/freemarker/core/version.properties";
 
     private static final String[] SETTING_NAMES_SNAKE_CASE = new String[] {
-        // Must be sorted alphabetically!
-        ExtendableBuilder.AUTO_ESCAPING_POLICY_KEY_SNAKE_CASE,
-        ExtendableBuilder.INCOMPATIBLE_IMPROVEMENTS_KEY_SNAKE_CASE,
-        ExtendableBuilder.LOCALIZED_TEMPLATE_LOOKUP_KEY_SNAKE_CASE,
-        ExtendableBuilder.NAMING_CONVENTION_KEY_SNAKE_CASE,
-        ExtendableBuilder.OUTPUT_FORMAT_KEY_SNAKE_CASE,
-        ExtendableBuilder.RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_SNAKE_CASE,
-        ExtendableBuilder.REGISTERED_CUSTOM_OUTPUT_FORMATS_KEY_SNAKE_CASE,
-        ExtendableBuilder.SHARED_VARIABLES_KEY_SNAKE_CASE,
-        ExtendableBuilder.SOURCE_ENCODING_KEY_SNAKE_CASE,
-        ExtendableBuilder.TAB_SIZE_KEY_SNAKE_CASE,
-        ExtendableBuilder.TAG_SYNTAX_KEY_SNAKE_CASE,
-        ExtendableBuilder.TEMPLATE_CACHE_STORAGE_KEY_SNAKE_CASE,
-        ExtendableBuilder.TEMPLATE_CONFIGURATIONS_KEY_SNAKE_CASE,
-        ExtendableBuilder.TEMPLATE_LANGUAGE_KEY_SNAKE_CASE,
-        ExtendableBuilder.TEMPLATE_LOADER_KEY_SNAKE_CASE,
-        ExtendableBuilder.TEMPLATE_LOOKUP_STRATEGY_KEY_SNAKE_CASE,
-        ExtendableBuilder.TEMPLATE_NAME_FORMAT_KEY_SNAKE_CASE,
-        ExtendableBuilder.TEMPLATE_UPDATE_DELAY_KEY_SNAKE_CASE,
-        ExtendableBuilder.WHITESPACE_STRIPPING_KEY_SNAKE_CASE,
+            // Must be sorted alphabetically!
+            ExtendableBuilder.INCOMPATIBLE_IMPROVEMENTS_KEY_SNAKE_CASE,
+            ExtendableBuilder.LOCALIZED_TEMPLATE_LOOKUP_KEY_SNAKE_CASE,
+            ExtendableBuilder.REGISTERED_CUSTOM_OUTPUT_FORMATS_KEY_SNAKE_CASE,
+            ExtendableBuilder.SHARED_VARIABLES_KEY_SNAKE_CASE,
+            ExtendableBuilder.TEMPLATE_CACHE_STORAGE_KEY_SNAKE_CASE,
+            ExtendableBuilder.TEMPLATE_CONFIGURATIONS_KEY_SNAKE_CASE,
+            ExtendableBuilder.TEMPLATE_LOADER_KEY_SNAKE_CASE,
+            ExtendableBuilder.TEMPLATE_LOOKUP_STRATEGY_KEY_SNAKE_CASE,
+            ExtendableBuilder.TEMPLATE_NAME_FORMAT_KEY_SNAKE_CASE,
+            ExtendableBuilder.TEMPLATE_UPDATE_DELAY_KEY_SNAKE_CASE
     };
 
     private static final String[] SETTING_NAMES_CAMEL_CASE = new String[] {
-        // Must be sorted alphabetically!
-        ExtendableBuilder.AUTO_ESCAPING_POLICY_KEY_CAMEL_CASE,
-        ExtendableBuilder.INCOMPATIBLE_IMPROVEMENTS_KEY_CAMEL_CASE,
-        ExtendableBuilder.LOCALIZED_TEMPLATE_LOOKUP_KEY_CAMEL_CASE,
-        ExtendableBuilder.NAMING_CONVENTION_KEY_CAMEL_CASE,
-        ExtendableBuilder.OUTPUT_FORMAT_KEY_CAMEL_CASE,
-        ExtendableBuilder.RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_CAMEL_CASE,
-        ExtendableBuilder.REGISTERED_CUSTOM_OUTPUT_FORMATS_KEY_CAMEL_CASE,
-        ExtendableBuilder.SHARED_VARIABLES_KEY_CAMEL_CASE,
-        ExtendableBuilder.SOURCE_ENCODING_KEY_CAMEL_CASE,
-        ExtendableBuilder.TAB_SIZE_KEY_CAMEL_CASE,
-        ExtendableBuilder.TAG_SYNTAX_KEY_CAMEL_CASE,
-        ExtendableBuilder.TEMPLATE_CACHE_STORAGE_KEY_CAMEL_CASE,
-        ExtendableBuilder.TEMPLATE_CONFIGURATIONS_KEY_CAMEL_CASE,
-        ExtendableBuilder.TEMPLATE_LANGUAGE_KEY_CAMEL_CASE,
-        ExtendableBuilder.TEMPLATE_LOADER_KEY_CAMEL_CASE,
-        ExtendableBuilder.TEMPLATE_LOOKUP_STRATEGY_KEY_CAMEL_CASE,
-        ExtendableBuilder.TEMPLATE_NAME_FORMAT_KEY_CAMEL_CASE,
-        ExtendableBuilder.TEMPLATE_UPDATE_DELAY_KEY_CAMEL_CASE,
-        ExtendableBuilder.WHITESPACE_STRIPPING_KEY_CAMEL_CASE
+            // Must be sorted alphabetically!
+            ExtendableBuilder.INCOMPATIBLE_IMPROVEMENTS_KEY_CAMEL_CASE,
+            ExtendableBuilder.LOCALIZED_TEMPLATE_LOOKUP_KEY_CAMEL_CASE,
+            ExtendableBuilder.REGISTERED_CUSTOM_OUTPUT_FORMATS_KEY_CAMEL_CASE,
+            ExtendableBuilder.SHARED_VARIABLES_KEY_CAMEL_CASE,
+            ExtendableBuilder.TEMPLATE_CACHE_STORAGE_KEY_CAMEL_CASE,
+            ExtendableBuilder.TEMPLATE_CONFIGURATIONS_KEY_CAMEL_CASE,
+            ExtendableBuilder.TEMPLATE_LOADER_KEY_CAMEL_CASE,
+            ExtendableBuilder.TEMPLATE_LOOKUP_STRATEGY_KEY_CAMEL_CASE,
+            ExtendableBuilder.TEMPLATE_NAME_FORMAT_KEY_CAMEL_CASE,
+            ExtendableBuilder.TEMPLATE_UPDATE_DELAY_KEY_CAMEL_CASE
     };
     
     private static final Map<String, OutputFormat> STANDARD_OUTPUT_FORMATS;
@@ -1659,127 +1641,75 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
             implements TopLevelConfiguration, org.apache.freemarker.core.util.CommonBuilder<Configuration> {
 
         /** Legacy, snake case ({@code like_this}) variation of the setting name. */
-        public static final String SOURCE_ENCODING_KEY_SNAKE_CASE = "source_encoding";
-        /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
-        public static final String SOURCE_ENCODING_KEY = SOURCE_ENCODING_KEY_SNAKE_CASE;
-        /** Modern, camel case ({@code likeThis}) variation of the setting name. */
-        public static final String SOURCE_ENCODING_KEY_CAMEL_CASE = "sourceEncoding";
-        /** Legacy, snake case ({@code like_this}) variation of the setting name. */
         public static final String LOCALIZED_TEMPLATE_LOOKUP_KEY_SNAKE_CASE = "localized_template_lookup";
         /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
         public static final String LOCALIZED_TEMPLATE_LOOKUP_KEY = LOCALIZED_TEMPLATE_LOOKUP_KEY_SNAKE_CASE;
         /** Modern, camel case ({@code likeThis}) variation of the setting name. */
         public static final String LOCALIZED_TEMPLATE_LOOKUP_KEY_CAMEL_CASE = "localizedTemplateLookup";
-        /** Legacy, snake case ({@code like_this}) variation of the setting name. */
-        public static final String WHITESPACE_STRIPPING_KEY_SNAKE_CASE = "whitespace_stripping";
-        /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
-        public static final String WHITESPACE_STRIPPING_KEY = WHITESPACE_STRIPPING_KEY_SNAKE_CASE;
-        /** Modern, camel case ({@code likeThis}) variation of the setting name. */
-        public static final String WHITESPACE_STRIPPING_KEY_CAMEL_CASE = "whitespaceStripping";
-        /** Legacy, snake case ({@code like_this}) variation of the setting name. */
-        public static final String OUTPUT_FORMAT_KEY_SNAKE_CASE = "output_format";
-        /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
-        public static final String OUTPUT_FORMAT_KEY = OUTPUT_FORMAT_KEY_SNAKE_CASE;
-        /** Modern, camel case ({@code likeThis}) variation of the setting name. */
-        public static final String OUTPUT_FORMAT_KEY_CAMEL_CASE = "outputFormat";
-        /** Legacy, snake case ({@code like_this}) variation of the setting name. */
-        public static final String RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_SNAKE_CASE = "recognize_standard_file_extensions";
-        /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
-        public static final String RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY
-                = RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_SNAKE_CASE;
-        /** Modern, camel case ({@code likeThis}) variation of the setting name. */
-        public static final String RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_CAMEL_CASE = "recognizeStandardFileExtensions";
+
         /** Legacy, snake case ({@code like_this}) variation of the setting name. */
         public static final String REGISTERED_CUSTOM_OUTPUT_FORMATS_KEY_SNAKE_CASE = "registered_custom_output_formats";
         /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
         public static final String REGISTERED_CUSTOM_OUTPUT_FORMATS_KEY = REGISTERED_CUSTOM_OUTPUT_FORMATS_KEY_SNAKE_CASE;
         /** Modern, camel case ({@code likeThis}) variation of the setting name. */
         public static final String REGISTERED_CUSTOM_OUTPUT_FORMATS_KEY_CAMEL_CASE = "registeredCustomOutputFormats";
-        /** Legacy, snake case ({@code like_this}) variation of the setting name. */
-        public static final String AUTO_ESCAPING_POLICY_KEY_SNAKE_CASE = "auto_escaping_policy";
-        /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
-        public static final String AUTO_ESCAPING_POLICY_KEY = AUTO_ESCAPING_POLICY_KEY_SNAKE_CASE;
-        /** Modern, camel case ({@code likeThis}) variation of the setting name. */
-        public static final String AUTO_ESCAPING_POLICY_KEY_CAMEL_CASE = "autoEscapingPolicy";
+
         /** Legacy, snake case ({@code like_this}) variation of the setting name. */
         public static final String TEMPLATE_CACHE_STORAGE_KEY_SNAKE_CASE = "template_cache_storage";
         /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
         public static final String TEMPLATE_CACHE_STORAGE_KEY = TEMPLATE_CACHE_STORAGE_KEY_SNAKE_CASE;
         /** Modern, camel case ({@code likeThis}) variation of the setting name. */
         public static final String TEMPLATE_CACHE_STORAGE_KEY_CAMEL_CASE = "templateCacheStorage";
+
         /** Legacy, snake case ({@code like_this}) variation of the setting name. */
         public static final String TEMPLATE_UPDATE_DELAY_KEY_SNAKE_CASE = "template_update_delay";
         /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
         public static final String TEMPLATE_UPDATE_DELAY_KEY = TEMPLATE_UPDATE_DELAY_KEY_SNAKE_CASE;
         /** Modern, camel case ({@code likeThis}) variation of the setting name. */
         public static final String TEMPLATE_UPDATE_DELAY_KEY_CAMEL_CASE = "templateUpdateDelay";
-        /** Legacy, snake case ({@code like_this}) variation of the setting name. */
-        public static final String AUTO_INCLUDE_KEY_SNAKE_CASE = "auto_include";
-        /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
-        public static final String AUTO_INCLUDE_KEY = AUTO_INCLUDE_KEY_SNAKE_CASE;
-        /** Modern, camel case ({@code likeThis}) variation of the setting name. */
-        public static final String AUTO_INCLUDE_KEY_CAMEL_CASE = "autoInclude";
-        /** Legacy, snake case ({@code like_this}) variation of the setting name. */
-        public static final String TEMPLATE_LANGUAGE_KEY_SNAKE_CASE = "template_language";
-        /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
-        public static final String TEMPLATE_LANGUAGE_KEY = TEMPLATE_LANGUAGE_KEY_SNAKE_CASE;
-        /** Modern, camel case ({@code likeThis}) variation of the setting name. */
-        public static final String TEMPLATE_LANGUAGE_KEY_CAMEL_CASE = "templateLanguage";
-        /** Legacy, snake case ({@code like_this}) variation of the setting name. */
-        public static final String TAG_SYNTAX_KEY_SNAKE_CASE = "tag_syntax";
-        /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
-        public static final String TAG_SYNTAX_KEY = TAG_SYNTAX_KEY_SNAKE_CASE;
-        /** Modern, camel case ({@code likeThis}) variation of the setting name. */
-        public static final String TAG_SYNTAX_KEY_CAMEL_CASE = "tagSyntax";
-        /** Legacy, snake case ({@code like_this}) variation of the setting name. */
-        public static final String NAMING_CONVENTION_KEY_SNAKE_CASE = "naming_convention";
-        /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
-        public static final String NAMING_CONVENTION_KEY = NAMING_CONVENTION_KEY_SNAKE_CASE;
-        /** Modern, camel case ({@code likeThis}) variation of the setting name. */
-        public static final String NAMING_CONVENTION_KEY_CAMEL_CASE = "namingConvention";
-        /** Legacy, snake case ({@code like_this}) variation of the setting name. */
-        public static final String TAB_SIZE_KEY_SNAKE_CASE = "tab_size";
-        /** Alias to the {@code ..._SNAKE_CASE} variation. */
-        public static final String TAB_SIZE_KEY = TAB_SIZE_KEY_SNAKE_CASE;
-        /** Modern, camel case ({@code likeThis}) variation of the setting name. */
-        public static final String TAB_SIZE_KEY_CAMEL_CASE = "tabSize";
+
         /** Legacy, snake case ({@code like_this}) variation of the setting name. */
         public static final String TEMPLATE_LOADER_KEY_SNAKE_CASE = "template_loader";
         /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
         public static final String TEMPLATE_LOADER_KEY = TEMPLATE_LOADER_KEY_SNAKE_CASE;
         /** Modern, camel case ({@code likeThis}) variation of the setting name. */
         public static final String TEMPLATE_LOADER_KEY_CAMEL_CASE = "templateLoader";
+
         /** Legacy, snake case ({@code like_this}) variation of the setting name. */
         public static final String TEMPLATE_LOOKUP_STRATEGY_KEY_SNAKE_CASE = "template_lookup_strategy";
         /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
         public static final String TEMPLATE_LOOKUP_STRATEGY_KEY = TEMPLATE_LOOKUP_STRATEGY_KEY_SNAKE_CASE;
         /** Modern, camel case ({@code likeThis}) variation of the setting name. */
         public static final String TEMPLATE_LOOKUP_STRATEGY_KEY_CAMEL_CASE = "templateLookupStrategy";
+
         /** Legacy, snake case ({@code like_this}) variation of the setting name. */
         public static final String TEMPLATE_NAME_FORMAT_KEY_SNAKE_CASE = "template_name_format";
         /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
         public static final String TEMPLATE_NAME_FORMAT_KEY = TEMPLATE_NAME_FORMAT_KEY_SNAKE_CASE;
         /** Modern, camel case ({@code likeThis}) variation of the setting name. */
         public static final String TEMPLATE_NAME_FORMAT_KEY_CAMEL_CASE = "templateNameFormat";
+
         /** Legacy, snake case ({@code like_this}) variation of the setting name. */
         public static final String SHARED_VARIABLES_KEY_SNAKE_CASE = "shared_variables";
         /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
         public static final String SHARED_VARIABLES_KEY = SHARED_VARIABLES_KEY_SNAKE_CASE;
         /** Modern, camel case ({@code likeThis}) variation of the setting name. */
         public static final String SHARED_VARIABLES_KEY_CAMEL_CASE = "sharedVariables";
+
         /** Legacy, snake case ({@code like_this}) variation of the setting name. */
         public static final String TEMPLATE_CONFIGURATIONS_KEY_SNAKE_CASE = "template_configurations";
         /** Alias to the {@code ..._SNAKE_CASE} variation. */
         public static final String TEMPLATE_CONFIGURATIONS_KEY = TEMPLATE_CONFIGURATIONS_KEY_SNAKE_CASE;
         /** Modern, camel case ({@code likeThis}) variation of the setting name. */
         public static final String TEMPLATE_CONFIGURATIONS_KEY_CAMEL_CASE = "templateConfigurations";
+
         /** Legacy, snake case ({@code like_this}) variation of the setting name. */
         public static final String INCOMPATIBLE_IMPROVEMENTS_KEY_SNAKE_CASE = "incompatible_improvements";
         /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
         public static final String INCOMPATIBLE_IMPROVEMENTS_KEY = INCOMPATIBLE_IMPROVEMENTS_KEY_SNAKE_CASE;
         /** Modern, camel case ({@code likeThis}) variation of the setting name. */
         public static final String INCOMPATIBLE_IMPROVEMENTS_KEY_CAMEL_CASE = "incompatibleImprovements";
-        // Set early in the constructor to non-null
+
         private Version incompatibleImprovements = Configuration.VERSION_3_0_0;
 
         private TemplateResolver templateResolver;
@@ -1799,7 +1729,6 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
         private boolean templateUpdateDelayMillisecondsSet;
         private Boolean localizedTemplateLookup;
         private boolean localizedTemplateLookupSet;
-
         private Collection<OutputFormat> registeredCustomOutputFormats;
         private Map<String, Object> sharedVariables;
 
@@ -1829,44 +1758,18 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
 
         @Override
         public void setSetting(String name, String value) throws ConfigurationException {
-            boolean unknown = false;
+            boolean nameUnhandled = false;
             try {
+                // TODO [FM3] Do we still need this?
                 if ("TemplateUpdateInterval".equalsIgnoreCase(name)) {
                     name = TEMPLATE_UPDATE_DELAY_KEY;
                 } else if ("DefaultEncoding".equalsIgnoreCase(name)) {
                     name = SOURCE_ENCODING_KEY;
                 }
 
-                if (SOURCE_ENCODING_KEY_SNAKE_CASE.equals(name) || SOURCE_ENCODING_KEY_CAMEL_CASE.equals(name)) {
-                    if (JVM_DEFAULT_VALUE.equalsIgnoreCase(value)) {
-                        setSourceEncoding(Charset.defaultCharset());
-                    } else {
-                        setSourceEncoding(Charset.forName(value));
-                    }
-                } else if (LOCALIZED_TEMPLATE_LOOKUP_KEY_SNAKE_CASE.equals(name)
+                if (LOCALIZED_TEMPLATE_LOOKUP_KEY_SNAKE_CASE.equals(name)
                         || LOCALIZED_TEMPLATE_LOOKUP_KEY_CAMEL_CASE.equals(name)) {
                     setLocalizedTemplateLookup(_StringUtil.getYesNo(value));
-                } else if (WHITESPACE_STRIPPING_KEY_SNAKE_CASE.equals(name)
-                        || WHITESPACE_STRIPPING_KEY_CAMEL_CASE.equals(name)) {
-                    setWhitespaceStripping(_StringUtil.getYesNo(value));
-                } else if (AUTO_ESCAPING_POLICY_KEY_SNAKE_CASE.equals(name) || AUTO_ESCAPING_POLICY_KEY_CAMEL_CASE.equals(name)) {
-                    if ("enable_if_default".equals(value) || "enableIfDefault".equals(value)) {
-                        setAutoEscapingPolicy(AutoEscapingPolicy.ENABLE_IF_DEFAULT);
-                    } else if ("enable_if_supported".equals(value) || "enableIfSupported".equals(value)) {
-                        setAutoEscapingPolicy(AutoEscapingPolicy.ENABLE_IF_SUPPORTED);
-                    } else if ("disable".equals(value)) {
-                        setAutoEscapingPolicy(AutoEscapingPolicy.DISABLE);
-                    } else {
-                        throw new InvalidSettingValueException( name, value,
-                                "No such predefined auto escaping policy name");
-                    }
-                } else if (OUTPUT_FORMAT_KEY_SNAKE_CASE.equals(name) || OUTPUT_FORMAT_KEY_CAMEL_CASE.equals(name)) {
-                    if (value.equalsIgnoreCase(DEFAULT_VALUE)) {
-                        unsetOutputFormat();
-                    } else {
-                        setOutputFormat((OutputFormat) _ObjectBuilderSettingEvaluator.eval(
-                                value, OutputFormat.class, true, _SettingEvaluationEnvironment.getCurrent()));
-                    }
                 } else if (REGISTERED_CUSTOM_OUTPUT_FORMATS_KEY_SNAKE_CASE.equals(name)
                         || REGISTERED_CUSTOM_OUTPUT_FORMATS_KEY_CAMEL_CASE.equals(name)) {
                     List list = (List) _ObjectBuilderSettingEvaluator.eval(
@@ -1878,13 +1781,6 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
                         }
                     }
                     setRegisteredCustomOutputFormats(list);
-                } else if (RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_SNAKE_CASE.equals(name)
-                        || RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_CAMEL_CASE.equals(name)) {
-                    if (value.equalsIgnoreCase(DEFAULT_VALUE)) {
-                        unsetRecognizeStandardFileExtensions();
-                    } else {
-                        setRecognizeStandardFileExtensions(_StringUtil.getYesNo(value));
-                    }
                 } else if (TEMPLATE_CACHE_STORAGE_KEY_SNAKE_CASE.equals(name) || TEMPLATE_CACHE_STORAGE_KEY_CAMEL_CASE.equals(name)) {
                     if (value.equalsIgnoreCase(DEFAULT_VALUE)) {
                         unsetTemplateCacheStorage();
@@ -1969,37 +1865,6 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
                         }
                     }
                     setSharedVariables((Map) sharedVariables);
-                } else if (TEMPLATE_LANGUAGE_KEY_SNAKE_CASE.equals(name) || TEMPLATE_LANGUAGE_KEY_CAMEL_CASE.equals(name)) {
-                    if ("FTL".equals(value)) {
-                        setTemplateLanguage(TemplateLanguage.FTL);
-                    } else if ("static_text".equals(value) || "staticText".equals(value)) {
-                        setTemplateLanguage(TemplateLanguage.STATIC_TEXT);
-                    } else {
-                        throw new InvalidSettingValueException(name, value, "Unsupported template language name");
-                    }
-                } else if (TAG_SYNTAX_KEY_SNAKE_CASE.equals(name) || TAG_SYNTAX_KEY_CAMEL_CASE.equals(name)) {
-                    if ("auto_detect".equals(value) || "autoDetect".equals(value)) {
-                        setTagSyntax(TagSyntax.AUTO_DETECT);
-                    } else if ("angle_bracket".equals(value) || "angleBracket".equals(value)) {
-                        setTagSyntax(TagSyntax.ANGLE_BRACKET);
-                    } else if ("square_bracket".equals(value) || "squareBracket".equals(value)) {
-                        setTagSyntax(TagSyntax.SQUARE_BRACKET);
-                    } else {
-                        throw new InvalidSettingValueException(name, value, "No such predefined tag syntax name");
-                    }
-                } else if (NAMING_CONVENTION_KEY_SNAKE_CASE.equals(name) || NAMING_CONVENTION_KEY_CAMEL_CASE.equals(name)) {
-                    if ("auto_detect".equals(value) || "autoDetect".equals(value)) {
-                        setNamingConvention(NamingConvention.AUTO_DETECT);
-                    } else if ("legacy".equals(value)) {
-                        setNamingConvention(NamingConvention.LEGACY);
-                    } else if ("camel_case".equals(value) || "camelCase".equals(value)) {
-                        setNamingConvention(NamingConvention.CAMEL_CASE);
-                    } else {
-                        throw new InvalidSettingValueException(name, value,
-                                "No such predefined naming convention name.");
-                    }
-                } else if (TAB_SIZE_KEY_SNAKE_CASE.equals(name) || TAB_SIZE_KEY_CAMEL_CASE.equals(name)) {
-                    setTabSize(Integer.parseInt(value));
                 } else if (INCOMPATIBLE_IMPROVEMENTS_KEY_SNAKE_CASE.equals(name)
                         || INCOMPATIBLE_IMPROVEMENTS_KEY_CAMEL_CASE.equals(name)) {
                     setIncompatibleImprovements(new Version(value));
@@ -2039,14 +1904,14 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
                                 value, TemplateConfigurationFactory.class, false, _SettingEvaluationEnvironment.getCurrent()));
                     }
                 } else {
-                    unknown = true;
+                    nameUnhandled = true;
                 }
             } catch (InvalidSettingValueException e) {
                 throw e;
             } catch (Exception e) {
                 throw new InvalidSettingValueException(name, value, e);
             }
-            if (unknown) {
+            if (nameUnhandled) {
                 super.setSetting(name, value);
             }
         }
@@ -2063,7 +1928,7 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
          */
         public static Set<String> getSettingNames(boolean camelCase) {
             return new _UnmodifiableCompositeSet<>(
-                    MutableProcessingConfiguration.getSettingNames(camelCase),
+                    MutableParsingAndProcessingConfiguration.getSettingNames(camelCase),
                     new _SortedArraySet<>(camelCase ? SETTING_NAMES_CAMEL_CASE : SETTING_NAMES_SNAKE_CASE));
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/a9038a8b/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 49cc921..1c6aa5f 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
@@ -21,17 +21,111 @@ package org.apache.freemarker.core;
 
 import java.io.InputStream;
 import java.nio.charset.Charset;
+import java.util.Set;
 
 import org.apache.freemarker.core.outputformat.OutputFormat;
 import org.apache.freemarker.core.outputformat.impl.UndefinedOutputFormat;
 import org.apache.freemarker.core.templateresolver.TemplateLoader;
 import org.apache.freemarker.core.util._NullArgumentException;
+import org.apache.freemarker.core.util._SortedArraySet;
+import org.apache.freemarker.core.util._StringUtil;
+import org.apache.freemarker.core.util._UnmodifiableCompositeSet;
 
 public abstract class MutableParsingAndProcessingConfiguration<
         SelfT extends MutableParsingAndProcessingConfiguration<SelfT>>
         extends MutableProcessingConfiguration<SelfT>
         implements ParsingAndProcessingConfiguration {
 
+    /** Legacy, snake case ({@code like_this}) variation of the setting name. */
+    public static final String OUTPUT_FORMAT_KEY_SNAKE_CASE = "output_format";
+    /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
+    public static final String OUTPUT_FORMAT_KEY = OUTPUT_FORMAT_KEY_SNAKE_CASE;
+    /** Modern, camel case ({@code likeThis}) variation of the setting name. */
+    public static final String OUTPUT_FORMAT_KEY_CAMEL_CASE = "outputFormat";
+
+    /** Legacy, snake case ({@code like_this}) variation of the setting name. */
+    public static final String SOURCE_ENCODING_KEY_SNAKE_CASE = "source_encoding";
+    /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
+    public static final String SOURCE_ENCODING_KEY = SOURCE_ENCODING_KEY_SNAKE_CASE;
+    /** Modern, camel case ({@code likeThis}) variation of the setting name. */
+    public static final String SOURCE_ENCODING_KEY_CAMEL_CASE = "sourceEncoding";
+
+    /** Legacy, snake case ({@code like_this}) variation of the setting name. */
+    public static final String WHITESPACE_STRIPPING_KEY_SNAKE_CASE = "whitespace_stripping";
+    /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
+    public static final String WHITESPACE_STRIPPING_KEY = WHITESPACE_STRIPPING_KEY_SNAKE_CASE;
+    /** Modern, camel case ({@code likeThis}) variation of the setting name. */
+    public static final String WHITESPACE_STRIPPING_KEY_CAMEL_CASE = "whitespaceStripping";
+
+    /** Legacy, snake case ({@code like_this}) variation of the setting name. */
+    public static final String AUTO_ESCAPING_POLICY_KEY_SNAKE_CASE = "auto_escaping_policy";
+    /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
+    public static final String AUTO_ESCAPING_POLICY_KEY = AUTO_ESCAPING_POLICY_KEY_SNAKE_CASE;
+    /** Modern, camel case ({@code likeThis}) variation of the setting name. */
+    public static final String AUTO_ESCAPING_POLICY_KEY_CAMEL_CASE = "autoEscapingPolicy";
+
+    /** Legacy, snake case ({@code like_this}) variation of the setting name. */
+    public static final String RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_SNAKE_CASE = "recognize_standard_file_extensions";
+    /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
+    public static final String RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY
+            = RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_SNAKE_CASE;
+    /** Modern, camel case ({@code likeThis}) variation of the setting name. */
+    public static final String RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_CAMEL_CASE = "recognizeStandardFileExtensions";
+
+    /** Legacy, snake case ({@code like_this}) variation of the setting name. */
+    public static final String TEMPLATE_LANGUAGE_KEY_SNAKE_CASE = "template_language";
+    /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
+    public static final String TEMPLATE_LANGUAGE_KEY = TEMPLATE_LANGUAGE_KEY_SNAKE_CASE;
+    /** Modern, camel case ({@code likeThis}) variation of the setting name. */
+    public static final String TEMPLATE_LANGUAGE_KEY_CAMEL_CASE = "templateLanguage";
+
+    /** Legacy, snake case ({@code like_this}) variation of the setting name. */
+    public static final String TAG_SYNTAX_KEY_SNAKE_CASE = "tag_syntax";
+    /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
+    public static final String TAG_SYNTAX_KEY = TAG_SYNTAX_KEY_SNAKE_CASE;
+    /** Modern, camel case ({@code likeThis}) variation of the setting name. */
+    public static final String TAG_SYNTAX_KEY_CAMEL_CASE = "tagSyntax";
+
+    /** Legacy, snake case ({@code like_this}) variation of the setting name. */
+    public static final String NAMING_CONVENTION_KEY_SNAKE_CASE = "naming_convention";
+    /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
+    public static final String NAMING_CONVENTION_KEY = NAMING_CONVENTION_KEY_SNAKE_CASE;
+    /** Modern, camel case ({@code likeThis}) variation of the setting name. */
+    public static final String NAMING_CONVENTION_KEY_CAMEL_CASE = "namingConvention";
+
+    /** Legacy, snake case ({@code like_this}) variation of the setting name. */
+    public static final String TAB_SIZE_KEY_SNAKE_CASE = "tab_size";
+    /** Alias to the {@code ..._SNAKE_CASE} variation. */
+    public static final String TAB_SIZE_KEY = TAB_SIZE_KEY_SNAKE_CASE;
+    /** Modern, camel case ({@code likeThis}) variation of the setting name. */
+    public static final String TAB_SIZE_KEY_CAMEL_CASE = "tabSize";
+
+    private static final String[] SETTING_NAMES_SNAKE_CASE = new String[] {
+            // Must be sorted alphabetically!
+            AUTO_ESCAPING_POLICY_KEY_SNAKE_CASE,
+            NAMING_CONVENTION_KEY_SNAKE_CASE,
+            OUTPUT_FORMAT_KEY_SNAKE_CASE,
+            RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_SNAKE_CASE,
+            SOURCE_ENCODING_KEY_SNAKE_CASE,
+            TAB_SIZE_KEY_SNAKE_CASE,
+            TAG_SYNTAX_KEY_SNAKE_CASE,
+            TEMPLATE_LANGUAGE_KEY_SNAKE_CASE,
+            WHITESPACE_STRIPPING_KEY_SNAKE_CASE
+    };
+
+    private static final String[] SETTING_NAMES_CAMEL_CASE = new String[] {
+            // Must be sorted alphabetically!
+            AUTO_ESCAPING_POLICY_KEY_CAMEL_CASE,
+            NAMING_CONVENTION_KEY_CAMEL_CASE,
+            OUTPUT_FORMAT_KEY_CAMEL_CASE,
+            RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_CAMEL_CASE,
+            SOURCE_ENCODING_KEY_CAMEL_CASE,
+            TAB_SIZE_KEY_CAMEL_CASE,
+            TAG_SYNTAX_KEY_CAMEL_CASE,
+            TEMPLATE_LANGUAGE_KEY_CAMEL_CASE,
+            WHITESPACE_STRIPPING_KEY_CAMEL_CASE
+    };
+
     private TemplateLanguage templateLanguage;
     private TagSyntax tagSyntax;
     private NamingConvention namingConvention;
@@ -46,6 +140,94 @@ public abstract class MutableParsingAndProcessingConfiguration<
         super();
     }
 
+    @Override
+    public void setSetting(String name, String value) throws ConfigurationException {
+        boolean nameUnhandled = false;
+        try {
+            if (SOURCE_ENCODING_KEY_SNAKE_CASE.equals(name) || SOURCE_ENCODING_KEY_CAMEL_CASE.equals(name)) {
+                if (JVM_DEFAULT_VALUE.equalsIgnoreCase(value)) {
+                    setSourceEncoding(Charset.defaultCharset());
+                } else {
+                    setSourceEncoding(Charset.forName(value));
+                }
+            } else if (OUTPUT_FORMAT_KEY_SNAKE_CASE.equals(name) || OUTPUT_FORMAT_KEY_CAMEL_CASE.equals(name)) {
+                if (value.equalsIgnoreCase(DEFAULT_VALUE)) {
+                    unsetOutputFormat();
+                } else {
+                    setOutputFormat((OutputFormat) _ObjectBuilderSettingEvaluator.eval(
+                            value, OutputFormat.class, true, _SettingEvaluationEnvironment.getCurrent()));
+                }
+            } else if (WHITESPACE_STRIPPING_KEY_SNAKE_CASE.equals(name)
+                    || WHITESPACE_STRIPPING_KEY_CAMEL_CASE.equals(name)) {
+                setWhitespaceStripping(_StringUtil.getYesNo(value));
+            } else if (AUTO_ESCAPING_POLICY_KEY_SNAKE_CASE.equals(name) || AUTO_ESCAPING_POLICY_KEY_CAMEL_CASE.equals(name)) {
+                if ("enable_if_default".equals(value) || "enableIfDefault".equals(value)) {
+                    setAutoEscapingPolicy(AutoEscapingPolicy.ENABLE_IF_DEFAULT);
+                } else if ("enable_if_supported".equals(value) || "enableIfSupported".equals(value)) {
+                    setAutoEscapingPolicy(AutoEscapingPolicy.ENABLE_IF_SUPPORTED);
+                } else if ("disable".equals(value)) {
+                    setAutoEscapingPolicy(AutoEscapingPolicy.DISABLE);
+                } else {
+                    throw new InvalidSettingValueException( name, value,
+                            "No such predefined auto escaping policy name");
+                }
+            } else if (RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_SNAKE_CASE.equals(name)
+                    || RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_CAMEL_CASE.equals(name)) {
+                if (value.equalsIgnoreCase(DEFAULT_VALUE)) {
+                    unsetRecognizeStandardFileExtensions();
+                } else {
+                    setRecognizeStandardFileExtensions(_StringUtil.getYesNo(value));
+                }
+            } else if (TEMPLATE_LANGUAGE_KEY_SNAKE_CASE.equals(name) || TEMPLATE_LANGUAGE_KEY_CAMEL_CASE.equals(name)) {
+                if ("FTL".equals(value)) {
+                    setTemplateLanguage(TemplateLanguage.FTL);
+                } else if ("static_text".equals(value) || "staticText".equals(value)) {
+                    setTemplateLanguage(TemplateLanguage.STATIC_TEXT);
+                } else {
+                    throw new InvalidSettingValueException(name, value, "Unsupported template language name");
+                }
+            } else if (TAG_SYNTAX_KEY_SNAKE_CASE.equals(name) || TAG_SYNTAX_KEY_CAMEL_CASE.equals(name)) {
+                if ("auto_detect".equals(value) || "autoDetect".equals(value)) {
+                    setTagSyntax(TagSyntax.AUTO_DETECT);
+                } else if ("angle_bracket".equals(value) || "angleBracket".equals(value)) {
+                    setTagSyntax(TagSyntax.ANGLE_BRACKET);
+                } else if ("square_bracket".equals(value) || "squareBracket".equals(value)) {
+                    setTagSyntax(TagSyntax.SQUARE_BRACKET);
+                } else {
+                    throw new InvalidSettingValueException(name, value, "No such predefined tag syntax name");
+                }
+            } else if (NAMING_CONVENTION_KEY_SNAKE_CASE.equals(name) || NAMING_CONVENTION_KEY_CAMEL_CASE.equals(name)) {
+                if ("auto_detect".equals(value) || "autoDetect".equals(value)) {
+                    setNamingConvention(NamingConvention.AUTO_DETECT);
+                } else if ("legacy".equals(value)) {
+                    setNamingConvention(NamingConvention.LEGACY);
+                } else if ("camel_case".equals(value) || "camelCase".equals(value)) {
+                    setNamingConvention(NamingConvention.CAMEL_CASE);
+                } else {
+                    throw new InvalidSettingValueException(name, value,
+                            "No such predefined naming convention name.");
+                }
+            } else if (TAB_SIZE_KEY_SNAKE_CASE.equals(name) || TAB_SIZE_KEY_CAMEL_CASE.equals(name)) {
+                setTabSize(Integer.parseInt(value));
+            } else {
+                nameUnhandled = true;
+            }
+        } catch (InvalidSettingValueException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new InvalidSettingValueException(name, value, e);
+        }
+        if (nameUnhandled) {
+            super.setSetting(name, value);
+        }
+    }
+
+    public static Set<String> getSettingNames(boolean camelCase) {
+        return new _UnmodifiableCompositeSet<>(
+                MutableProcessingConfiguration.getSettingNames(camelCase),
+                new _SortedArraySet<>(camelCase ? SETTING_NAMES_CAMEL_CASE : SETTING_NAMES_SNAKE_CASE));
+    }
+
     /**
      * Setter pair of {@link #getTagSyntax()}.
      *



[2/2] incubator-freemarker git commit: Refined setSetting(String, String) and ..._KEY constatns so that they are split between the 3 classes of the inheritance chain: Configuration.ExtendableBuilder, MutableParsingAndProcessingConfiguration, MutableProc

Posted by dd...@apache.org.
Refined setSetting(String, String)  and ..._KEY constatns so that they are split between the 3 classes of the inheritance chain: Configuration.ExtendableBuilder, MutableParsingAndProcessingConfiguration, MutableProcessingConfigurationTest.


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

Branch: refs/heads/3
Commit: a9038a8b98055a2b2354d334c960520399d8c47a
Parents: 8680c06
Author: ddekany <dd...@apache.org>
Authored: Sun Jun 11 19:28:31 2017 +0200
Committer: ddekany <dd...@apache.org>
Committed: Sun Jun 11 19:28:31 2017 +0200

----------------------------------------------------------------------
 .../freemarker/core/ConfigurationTest.java      | 638 +------------------
 ...leParsingAndProcessingConfigurationTest.java | 382 +++++++++++
 .../MutableProcessingConfigurationTest.java     | 314 +++++++++
 .../apache/freemarker/core/Configuration.java   | 211 ++----
 ...utableParsingAndProcessingConfiguration.java | 182 ++++++
 5 files changed, 951 insertions(+), 776 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/a9038a8b/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java
index ae9bd74..58e7254 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java
@@ -31,7 +31,6 @@ import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
@@ -50,7 +49,6 @@ import org.apache.freemarker.core.outputformat.UnregisteredOutputFormatException
 import org.apache.freemarker.core.outputformat.impl.CombinedMarkupOutputFormat;
 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.core.templateresolver.CacheStorageWithGetSize;
 import org.apache.freemarker.core.templateresolver.ConditionalTemplateConfigurationFactory;
@@ -80,7 +78,6 @@ import org.apache.freemarker.core.userpkg.NameClashingDummyOutputFormat;
 import org.apache.freemarker.core.userpkg.SeldomEscapedOutputFormat;
 import org.apache.freemarker.core.util._CollectionUtil;
 import org.apache.freemarker.core.util._DateUtil;
-import org.apache.freemarker.core.util._NullArgumentException;
 import org.apache.freemarker.core.util._NullWriter;
 import org.apache.freemarker.core.util._StringUtil;
 import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory;
@@ -90,17 +87,11 @@ import org.junit.Test;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import junit.framework.TestCase;
-
-public class ConfigurationTest extends TestCase {
+public class ConfigurationTest {
 
     private static final Charset ISO_8859_2 = Charset.forName("ISO-8859-2");
 
-    public ConfigurationTest(String name) {
-        super(name);
-    }
-
+    @Test
     public void testUnsetAndIsSet() throws Exception {
         Configuration.ExtendableBuilder<?> cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
         
@@ -203,7 +194,8 @@ public class ConfigurationTest extends TestCase {
             assertTrue(cfgB.getTemplateCacheStorage() instanceof SoftCacheStorage);
         }
     }
-    
+
+    @Test
     public void testTemplateLoadingErrors() throws Exception {
         Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0)
                 .templateLoader(new ClassTemplateLoader(getClass(), "nosuchpackage"))
@@ -215,7 +207,8 @@ public class ConfigurationTest extends TestCase {
             assertThat(e.getMessage(), not(containsString("wasn't set")));
         }
     }
-    
+
+    @Test
     public void testVersion() {
         Version v = Configuration.getVersion();
         assertTrue(v.intValue() >= _CoreAPI.VERSION_INT_3_0_0);
@@ -232,7 +225,8 @@ public class ConfigurationTest extends TestCase {
             assertThat(e.getMessage(), containsString("3.0.0"));
         }
     }
-    
+
+    @Test
     public void testShowErrorTips() throws Exception {
         try {
             Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0).build();
@@ -379,7 +373,8 @@ public class ConfigurationTest extends TestCase {
         t.process(null, sw);
         assertEquals(expectedContent, sw.toString());
     }
-    
+
+    @Test
     public void testTemplateResolverCache() throws Exception {
         Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
         
@@ -403,6 +398,7 @@ public class ConfigurationTest extends TestCase {
         assertEquals(1, cache.getSize());
     }
 
+    @Test
     public void testTemplateNameFormat() throws Exception {
         StringTemplateLoader tl = new StringTemplateLoader();
         tl.putTemplate("a/b.ftl", "In a/b.ftl");
@@ -431,6 +427,7 @@ public class ConfigurationTest extends TestCase {
         }
     }
 
+    @Test
     public void testTemplateNameFormatSetSetting() throws Exception {
         Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
         assertSame(DefaultTemplateNameFormatFM2.INSTANCE, cfgB.getTemplateNameFormat());
@@ -443,6 +440,7 @@ public class ConfigurationTest extends TestCase {
         assertFalse(cfgB.isTemplateNameFormatSet());
     }
 
+    @Test
     public void testObjectWrapperSetSetting() throws Exception {
         Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
         {
@@ -457,7 +455,8 @@ public class ConfigurationTest extends TestCase {
             assertThat(cfgB.getObjectWrapper(), instanceOf(RestrictedObjectWrapper.class));
         }
     }
-    
+
+    @Test
     public void testTemplateLookupStrategyDefault() throws Exception {
         Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0)
                 .templateLoader(new ClassTemplateLoader(ConfigurationTest.class, ""))
@@ -466,6 +465,7 @@ public class ConfigurationTest extends TestCase {
         assertEquals("toCache1.ftl", cfg.getTemplate("toCache1.ftl").getSourceName());
     }
 
+    @Test
     public void testTemplateLookupStrategyCustom() throws Exception {
         final TemplateLookupStrategy myStrategy = new TemplateLookupStrategy() {
             @Override
@@ -481,7 +481,8 @@ public class ConfigurationTest extends TestCase {
         assertSame(myStrategy, cfg.getTemplateLookupStrategy());
         assertEquals("toCache2.ftl", cfg.getTemplate("toCache1.ftl").getSourceName());
     }
-    
+
+    @Test
     public void testSetTemplateConfigurations() throws Exception {
         Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
         assertNull(cfgB.getTemplateConfigurations());
@@ -544,73 +545,6 @@ public class ConfigurationTest extends TestCase {
         assertNull(cfgB.getTemplateConfigurations());
     }
 
-    public void testSetAutoEscaping() throws Exception {
-       Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
-    
-       assertEquals(AutoEscapingPolicy.ENABLE_IF_DEFAULT, cfgB.getAutoEscapingPolicy());
-
-       cfgB.setAutoEscapingPolicy(AutoEscapingPolicy.ENABLE_IF_SUPPORTED);
-       assertEquals(AutoEscapingPolicy.ENABLE_IF_SUPPORTED, cfgB.getAutoEscapingPolicy());
-
-       cfgB.setAutoEscapingPolicy(AutoEscapingPolicy.ENABLE_IF_DEFAULT);
-       assertEquals(AutoEscapingPolicy.ENABLE_IF_DEFAULT, cfgB.getAutoEscapingPolicy());
-
-       cfgB.setAutoEscapingPolicy(AutoEscapingPolicy.DISABLE);
-       assertEquals(AutoEscapingPolicy.DISABLE, cfgB.getAutoEscapingPolicy());
-       
-       cfgB.setSetting(Configuration.ExtendableBuilder.AUTO_ESCAPING_POLICY_KEY_CAMEL_CASE, "enableIfSupported");
-       assertEquals(AutoEscapingPolicy.ENABLE_IF_SUPPORTED, cfgB.getAutoEscapingPolicy());
-
-       cfgB.setSetting(Configuration.ExtendableBuilder.AUTO_ESCAPING_POLICY_KEY_CAMEL_CASE, "enable_if_supported");
-       assertEquals(AutoEscapingPolicy.ENABLE_IF_SUPPORTED, cfgB.getAutoEscapingPolicy());
-       
-       cfgB.setSetting(Configuration.ExtendableBuilder.AUTO_ESCAPING_POLICY_KEY_CAMEL_CASE, "enableIfDefault");
-       assertEquals(AutoEscapingPolicy.ENABLE_IF_DEFAULT, cfgB.getAutoEscapingPolicy());
-
-       cfgB.setSetting(Configuration.ExtendableBuilder.AUTO_ESCAPING_POLICY_KEY_CAMEL_CASE, "enable_if_default");
-       assertEquals(AutoEscapingPolicy.ENABLE_IF_DEFAULT, cfgB.getAutoEscapingPolicy());
-       
-       cfgB.setSetting(Configuration.ExtendableBuilder.AUTO_ESCAPING_POLICY_KEY_CAMEL_CASE, "disable");
-       assertEquals(AutoEscapingPolicy.DISABLE, cfgB.getAutoEscapingPolicy());
-    }
-
-    public void testSetOutputFormat() throws Exception {
-       Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
-       
-       assertEquals(UndefinedOutputFormat.INSTANCE, cfgB.getOutputFormat());
-       assertFalse(cfgB.isOutputFormatSet());
-       
-       try {
-           cfgB.setOutputFormat(null);
-           fail();
-       } catch (_NullArgumentException e) {
-           // Expected
-       }
-       
-       assertFalse(cfgB.isOutputFormatSet());
-       
-       cfgB.setSetting(Configuration.ExtendableBuilder.OUTPUT_FORMAT_KEY_CAMEL_CASE, XMLOutputFormat.class.getSimpleName());
-       assertEquals(XMLOutputFormat.INSTANCE, cfgB.getOutputFormat());
-       
-       cfgB.setSetting(Configuration.ExtendableBuilder.OUTPUT_FORMAT_KEY_SNAKE_CASE, HTMLOutputFormat.class.getSimpleName());
-       assertEquals(HTMLOutputFormat.INSTANCE, cfgB.getOutputFormat());
-       
-       cfgB.unsetOutputFormat();
-       assertEquals(UndefinedOutputFormat.INSTANCE, cfgB.getOutputFormat());
-       assertFalse(cfgB.isOutputFormatSet());
-       
-       cfgB.setOutputFormat(UndefinedOutputFormat.INSTANCE);
-       assertTrue(cfgB.isOutputFormatSet());
-       cfgB.setSetting(Configuration.ExtendableBuilder.OUTPUT_FORMAT_KEY_CAMEL_CASE, "default");
-       assertFalse(cfgB.isOutputFormatSet());
-       
-       try {
-           cfgB.setSetting(Configuration.ExtendableBuilder.OUTPUT_FORMAT_KEY, "null");
-       } catch (InvalidSettingValueException e) {
-           assertThat(e.getCause().getMessage(), containsString(UndefinedOutputFormat.class.getSimpleName()));
-       }
-    }
-    
     @Test
     public void testGetOutputFormatByName() throws Exception {
         Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0).build();
@@ -665,6 +599,7 @@ public class ConfigurationTest extends TestCase {
         }
     }
 
+    @Test
     public void testSetRegisteredCustomOutputFormats() throws Exception {
         Configuration.Builder cfg = new Configuration.Builder(Configuration.VERSION_3_0_0);
         
@@ -685,157 +620,7 @@ public class ConfigurationTest extends TestCase {
         }
     }
 
-    public void testSetRecognizeStandardFileExtensions() throws Exception {
-        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
-     
-        assertTrue(cfgB.getRecognizeStandardFileExtensions());
-        assertFalse(cfgB.isRecognizeStandardFileExtensionsSet());
-
-        cfgB.setRecognizeStandardFileExtensions(false);
-        assertFalse(cfgB.getRecognizeStandardFileExtensions());
-        assertTrue(cfgB.isRecognizeStandardFileExtensionsSet());
-     
-        cfgB.unsetRecognizeStandardFileExtensions();
-        assertTrue(cfgB.getRecognizeStandardFileExtensions());
-        assertFalse(cfgB.isRecognizeStandardFileExtensionsSet());
-        
-        cfgB.setRecognizeStandardFileExtensions(true);
-        assertTrue(cfgB.getRecognizeStandardFileExtensions());
-        assertTrue(cfgB.isRecognizeStandardFileExtensionsSet());
-     
-        cfgB.setSetting(Configuration.ExtendableBuilder.RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_CAMEL_CASE, "false");
-        assertFalse(cfgB.getRecognizeStandardFileExtensions());
-        assertTrue(cfgB.isRecognizeStandardFileExtensionsSet());
-        
-        cfgB.setSetting(Configuration.ExtendableBuilder.RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_SNAKE_CASE, "default");
-        assertTrue(cfgB.getRecognizeStandardFileExtensions());
-        assertFalse(cfgB.isRecognizeStandardFileExtensionsSet());
-     }
-    
-    public void testSetTimeZone() throws ConfigurationException {
-        TimeZone origSysDefTZ = TimeZone.getDefault();
-        try {
-            TimeZone sysDefTZ = TimeZone.getTimeZone("GMT-01");
-            TimeZone.setDefault(sysDefTZ);
-            
-            Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
-            assertEquals(sysDefTZ, cfgB.getTimeZone());
-            cfgB.setSetting(MutableProcessingConfiguration.TIME_ZONE_KEY, "JVM default");
-            assertEquals(sysDefTZ, cfgB.getTimeZone());
-            
-            TimeZone newSysDefTZ = TimeZone.getTimeZone("GMT+09");
-            TimeZone.setDefault(newSysDefTZ);
-            assertEquals(sysDefTZ, cfgB.getTimeZone());
-            cfgB.setSetting(MutableProcessingConfiguration.TIME_ZONE_KEY, "JVM default");
-            assertEquals(newSysDefTZ, cfgB.getTimeZone());
-        } finally {
-            TimeZone.setDefault(origSysDefTZ);
-        }
-    }
-    
-    public void testSetSQLDateAndTimeTimeZone() throws ConfigurationException {
-        TimeZone origSysDefTZ = TimeZone.getDefault();
-        try {
-            TimeZone sysDefTZ = TimeZone.getTimeZone("GMT-01");
-            TimeZone.setDefault(sysDefTZ);
-            
-            Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
-            assertNull(cfgB.getSQLDateAndTimeTimeZone());
-            
-            cfgB.setSQLDateAndTimeTimeZone(null);
-            assertNull(cfgB.getSQLDateAndTimeTimeZone());
-            
-            cfgB.setSetting(MutableProcessingConfiguration.SQL_DATE_AND_TIME_TIME_ZONE_KEY, "JVM default");
-            assertEquals(sysDefTZ, cfgB.getSQLDateAndTimeTimeZone());
-            
-            cfgB.setSetting(MutableProcessingConfiguration.SQL_DATE_AND_TIME_TIME_ZONE_KEY, "null");
-            assertNull(cfgB.getSQLDateAndTimeTimeZone());
-        } finally {
-            TimeZone.setDefault(origSysDefTZ);
-        }
-    }
-
-    public void testTimeZoneLayers() throws Exception {
-        TimeZone localTZ = TimeZone.getTimeZone("Europe/Brussels");
-
-        {
-            Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0).build();
-            Template t = new Template(null, "", cfg);
-            Environment env1 = t.createProcessingEnvironment(null, new StringWriter());
-            Environment env2 = t.createProcessingEnvironment(null, new StringWriter());
-
-            // cfg:
-            assertEquals(TimeZone.getDefault(), cfg.getTimeZone());
-            assertNull(cfg.getSQLDateAndTimeTimeZone());
-            // env:
-            assertEquals(TimeZone.getDefault(), env1.getTimeZone());
-            assertNull(env1.getSQLDateAndTimeTimeZone());
-            // env 2:
-            assertEquals(TimeZone.getDefault(), env2.getTimeZone());
-            assertNull(env2.getSQLDateAndTimeTimeZone());
-
-            env1.setSQLDateAndTimeTimeZone(_DateUtil.UTC);
-            // cfg:
-            assertEquals(TimeZone.getDefault(), cfg.getTimeZone());
-            assertNull(cfg.getSQLDateAndTimeTimeZone());
-            // env:
-            assertEquals(TimeZone.getDefault(), env1.getTimeZone());
-            assertEquals(_DateUtil.UTC, env1.getSQLDateAndTimeTimeZone());
-
-            env1.setTimeZone(localTZ);
-            // cfg:
-            assertEquals(TimeZone.getDefault(), cfg.getTimeZone());
-            assertNull(cfg.getSQLDateAndTimeTimeZone());
-            // env:
-            assertEquals(localTZ, env1.getTimeZone());
-            assertEquals(_DateUtil.UTC, env1.getSQLDateAndTimeTimeZone());
-            // env 2:
-            assertEquals(TimeZone.getDefault(), env2.getTimeZone());
-            assertNull(env2.getSQLDateAndTimeTimeZone());
-        }
-
-        {
-            TimeZone otherTZ1 = TimeZone.getTimeZone("GMT+05");
-            TimeZone otherTZ2 = TimeZone.getTimeZone("GMT+06");
-            Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0)
-                    .timeZone(otherTZ1)
-                    .sqlDateAndTimeTimeZone(otherTZ2)
-                    .build();
-
-            Template t = new Template(null, "", cfg);
-            Environment env1 = t.createProcessingEnvironment(null, new StringWriter());
-            Environment env2 = t.createProcessingEnvironment(null, new StringWriter());
-
-            env1.setTimeZone(localTZ);
-            env1.setSQLDateAndTimeTimeZone(_DateUtil.UTC);
-
-            // cfg:
-            assertEquals(otherTZ1, cfg.getTimeZone());
-            assertEquals(otherTZ2, cfg.getSQLDateAndTimeTimeZone());
-            // env:
-            assertEquals(localTZ, env1.getTimeZone());
-            assertEquals(_DateUtil.UTC, env1.getSQLDateAndTimeTimeZone());
-            // env 2:
-            assertEquals(otherTZ1, env2.getTimeZone());
-            assertEquals(otherTZ2, env2.getSQLDateAndTimeTimeZone());
-
-            try {
-                setTimeZoneToNull(env2);
-                fail();
-            } catch (IllegalArgumentException e) {
-                // expected
-            }
-            env2.setSQLDateAndTimeTimeZone(null);
-            assertEquals(otherTZ1, env2.getTimeZone());
-            assertNull(env2.getSQLDateAndTimeTimeZone());
-        }
-    }
-
-    @SuppressFBWarnings(value="NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS", justification="Expected to fail")
-    private void setTimeZoneToNull(Environment env2) {
-        env2.setTimeZone(null);
-    }
-    
+    @Test
     public void testSetICIViaSetSettingAPI() throws ConfigurationException {
         Configuration.Builder cfg = new Configuration.Builder(Configuration.VERSION_3_0_0);
         assertEquals(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS, cfg.getIncompatibleImprovements());
@@ -844,13 +629,7 @@ public class ConfigurationTest extends TestCase {
         assertEquals(Configuration.VERSION_3_0_0, cfg.getIncompatibleImprovements());
     }
 
-    public void testSetLogTemplateExceptionsViaSetSettingAPI() throws ConfigurationException {
-        Configuration.Builder cfg = new Configuration.Builder(Configuration.VERSION_3_0_0);
-        assertFalse(cfg.getLogTemplateExceptions());
-        cfg.setSetting(MutableProcessingConfiguration.LOG_TEMPLATE_EXCEPTIONS_KEY, "true");
-        assertTrue(cfg.getLogTemplateExceptions());
-    }
-    
+    @Test
     public void testSharedVariables() throws TemplateException, IOException {
         Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0)
                 .sharedVariables(ImmutableMap.of(
@@ -883,24 +662,6 @@ public class ConfigurationTest extends TestCase {
     }
 
     @Test
-    public void testApiBuiltinEnabled() throws Exception {
-        try {
-            new Template(
-                    null, "${1?api}",
-                    new Configuration.Builder(Configuration.VERSION_3_0_0).build())
-                    .process(null, _NullWriter.INSTANCE);
-            fail();
-        } catch (TemplateException e) {
-            assertThat(e.getMessage(), containsString(MutableProcessingConfiguration.API_BUILTIN_ENABLED_KEY));
-        }
-            
-        new Template(
-                null, "${m?api.hashCode()}",
-                new Configuration.Builder(Configuration.VERSION_3_0_0).apiBuiltinEnabled(true).build())
-                .process(Collections.singletonMap("m", new HashMap()), _NullWriter.INSTANCE);
-    }
-
-    @Test
     public void testTemplateUpdateDelay() throws Exception {
         Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
 
@@ -949,329 +710,17 @@ public class ConfigurationTest extends TestCase {
         cfgB.setSetting(Configuration.ExtendableBuilder.TEMPLATE_UPDATE_DELAY_KEY, "2h");
         assertEquals(1000L * 60 * 60 * 2, (Object) cfgB.getTemplateUpdateDelayMilliseconds());
     }
-    
-    @Test
-    @SuppressFBWarnings(value = "NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS ", justification = "Testing wrong args")
-    public void testSetCustomNumberFormat() throws Exception {
-        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
-        
-        try {
-            cfgB.setCustomNumberFormats(null);
-            fail();
-        } catch (IllegalArgumentException e) {
-            assertThat(e.getMessage(), containsString("null"));
-        }
-
-        try {
-            cfgB.setCustomNumberFormats(Collections.<String, TemplateNumberFormatFactory>singletonMap(
-                    "", HexTemplateNumberFormatFactory.INSTANCE));
-            fail();
-        } catch (IllegalArgumentException e) {
-            assertThat(e.getMessage(), containsString("0 length"));
-        }
-
-        try {
-            cfgB.setCustomNumberFormats(Collections.<String, TemplateNumberFormatFactory>singletonMap(
-                    "a_b", HexTemplateNumberFormatFactory.INSTANCE));
-            fail();
-        } catch (IllegalArgumentException e) {
-            assertThat(e.getMessage(), containsString("a_b"));
-        }
-
-        try {
-            cfgB.setCustomNumberFormats(Collections.<String, TemplateNumberFormatFactory>singletonMap(
-                    "a b", HexTemplateNumberFormatFactory.INSTANCE));
-            fail();
-        } catch (IllegalArgumentException e) {
-            assertThat(e.getMessage(), containsString("a b"));
-        }
-        
-        try {
-            cfgB.setCustomNumberFormats(ImmutableMap.<String, TemplateNumberFormatFactory>of(
-                    "a", HexTemplateNumberFormatFactory.INSTANCE,
-                    "@wrong", HexTemplateNumberFormatFactory.INSTANCE));
-            fail();
-        } catch (IllegalArgumentException e) {
-            assertThat(e.getMessage(), containsString("@wrong"));
-        }
-        
-        cfgB.setSetting(MutableProcessingConfiguration.CUSTOM_NUMBER_FORMATS_KEY_CAMEL_CASE,
-                "{ 'base': " + BaseNTemplateNumberFormatFactory.class.getName() + "() }");
-        assertEquals(
-                Collections.singletonMap("base", BaseNTemplateNumberFormatFactory.INSTANCE),
-                cfgB.getCustomNumberFormats());
-        
-        cfgB.setSetting(MutableProcessingConfiguration.CUSTOM_NUMBER_FORMATS_KEY_SNAKE_CASE,
-                "{ "
-                + "'base': " + BaseNTemplateNumberFormatFactory.class.getName() + "(), "
-                + "'hex': " + HexTemplateNumberFormatFactory.class.getName() + "()"
-                + " }");
-        assertEquals(
-                ImmutableMap.of(
-                        "base", BaseNTemplateNumberFormatFactory.INSTANCE,
-                        "hex", HexTemplateNumberFormatFactory.INSTANCE),
-                cfgB.getCustomNumberFormats());
-        
-        cfgB.setSetting(MutableProcessingConfiguration.CUSTOM_NUMBER_FORMATS_KEY, "{}");
-        assertEquals(Collections.emptyMap(), cfgB.getCustomNumberFormats());
-        
-        try {
-            cfgB.setSetting(MutableProcessingConfiguration.CUSTOM_NUMBER_FORMATS_KEY_CAMEL_CASE,
-                    "{ 'x': " + EpochMillisTemplateDateFormatFactory.class.getName() + "() }");
-            fail();
-        } catch (ConfigurationException e) {
-            assertThat(e.getCause().getMessage(), allOf(
-                    containsString(EpochMillisTemplateDateFormatFactory.class.getName()),
-                    containsString(TemplateNumberFormatFactory.class.getName())));
-        }
-    }
-
-    @Test
-    public void testSetTabSize() throws Exception {
-        String ftl = "${\t}";
-        
-        try {
-            new Template(null, ftl,
-                    new Configuration.Builder(Configuration.VERSION_3_0_0).build());
-            fail();
-        } catch (ParseException e) {
-            assertEquals(9, e.getColumnNumber());
-        }
-        
-        try {
-            new Template(null, ftl,
-                    new Configuration.Builder(Configuration.VERSION_3_0_0).tabSize(1).build());
-            fail();
-        } catch (ParseException e) {
-            assertEquals(4, e.getColumnNumber());
-        }
-        
-        try {
-            new Configuration.Builder(Configuration.VERSION_3_0_0).tabSize(0);
-            fail();
-        } catch (IllegalArgumentException e) {
-            // Expected
-        }
-        
-        try {
-            new Configuration.Builder(Configuration.VERSION_3_0_0).tabSize(257);
-            fail();
-        } catch (IllegalArgumentException e) {
-            // Expected
-        }
-    }
-
-    @Test
-    public void testTabSizeSetting() throws Exception {
-        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
-        assertEquals(8, cfgB.getTabSize());
-        cfgB.setSetting(Configuration.ExtendableBuilder.TAB_SIZE_KEY_CAMEL_CASE, "4");
-        assertEquals(4, cfgB.getTabSize());
-        cfgB.setSetting(Configuration.ExtendableBuilder.TAB_SIZE_KEY_SNAKE_CASE, "1");
-        assertEquals(1, cfgB.getTabSize());
-        
-        try {
-            cfgB.setSetting(Configuration.ExtendableBuilder.TAB_SIZE_KEY_SNAKE_CASE, "x");
-            fail();
-        } catch (ConfigurationException e) {
-            assertThat(e.getCause(), instanceOf(NumberFormatException.class));
-        }
-    }
-    
-    @SuppressFBWarnings(value="NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS", justification="We test failures")
-    @Test
-    public void testSetCustomDateFormat() throws Exception {
-        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
-        
-        try {
-            cfgB.setCustomDateFormats(null);
-            fail();
-        } catch (IllegalArgumentException e) {
-            assertThat(e.getMessage(), containsString("null"));
-        }
-        
-        try {
-            cfgB.setCustomDateFormats(Collections.<String, TemplateDateFormatFactory>singletonMap(
-                    "", EpochMillisTemplateDateFormatFactory.INSTANCE));
-            fail();
-        } catch (IllegalArgumentException e) {
-            assertThat(e.getMessage(), containsString("0 length"));
-        }
-
-        try {
-            cfgB.setCustomDateFormats(Collections.<String, TemplateDateFormatFactory>singletonMap(
-                    "a_b", EpochMillisTemplateDateFormatFactory.INSTANCE));
-            fail();
-        } catch (IllegalArgumentException e) {
-            assertThat(e.getMessage(), containsString("a_b"));
-        }
-
-        try {
-            cfgB.setCustomDateFormats(Collections.<String, TemplateDateFormatFactory>singletonMap(
-                    "a b", EpochMillisTemplateDateFormatFactory.INSTANCE));
-            fail();
-        } catch (IllegalArgumentException e) {
-            assertThat(e.getMessage(), containsString("a b"));
-        }
-        
-        try {
-            cfgB.setCustomDateFormats(ImmutableMap.<String, TemplateDateFormatFactory>of(
-                    "a", EpochMillisTemplateDateFormatFactory.INSTANCE,
-                    "@wrong", EpochMillisTemplateDateFormatFactory.INSTANCE));
-            fail();
-        } catch (IllegalArgumentException e) {
-            assertThat(e.getMessage(), containsString("@wrong"));
-        }
-        
-        cfgB.setSetting(MutableProcessingConfiguration.CUSTOM_DATE_FORMATS_KEY_CAMEL_CASE,
-                "{ 'epoch': " + EpochMillisTemplateDateFormatFactory.class.getName() + "() }");
-        assertEquals(
-                Collections.singletonMap("epoch", EpochMillisTemplateDateFormatFactory.INSTANCE),
-                cfgB.getCustomDateFormats());
-        
-        cfgB.setSetting(MutableProcessingConfiguration.CUSTOM_DATE_FORMATS_KEY_SNAKE_CASE,
-                "{ "
-                + "'epoch': " + EpochMillisTemplateDateFormatFactory.class.getName() + "(), "
-                + "'epochDiv': " + EpochMillisDivTemplateDateFormatFactory.class.getName() + "()"
-                + " }");
-        assertEquals(
-                ImmutableMap.of(
-                        "epoch", EpochMillisTemplateDateFormatFactory.INSTANCE,
-                        "epochDiv", EpochMillisDivTemplateDateFormatFactory.INSTANCE),
-                cfgB.getCustomDateFormats());
-        
-        cfgB.setSetting(MutableProcessingConfiguration.CUSTOM_DATE_FORMATS_KEY, "{}");
-        assertEquals(Collections.emptyMap(), cfgB.getCustomDateFormats());
-        
-        try {
-            cfgB.setSetting(MutableProcessingConfiguration.CUSTOM_DATE_FORMATS_KEY_CAMEL_CASE,
-                    "{ 'x': " + HexTemplateNumberFormatFactory.class.getName() + "() }");
-            fail();
-        } catch (ConfigurationException e) {
-            assertThat(e.getCause().getMessage(), allOf(
-                    containsString(HexTemplateNumberFormatFactory.class.getName()),
-                    containsString(TemplateDateFormatFactory.class.getName())));
-        }
-    }
-
-    public void testNamingConventionSetSetting() throws ConfigurationException {
-        Configuration.Builder cfg = new Configuration.Builder(Configuration.VERSION_3_0_0);
-
-        assertEquals(NamingConvention.AUTO_DETECT, cfg.getNamingConvention());
-        
-        cfg.setSetting("naming_convention", "legacy");
-        assertEquals(NamingConvention.LEGACY, cfg.getNamingConvention());
-        
-        cfg.setSetting("naming_convention", "camel_case");
-        assertEquals(NamingConvention.CAMEL_CASE, cfg.getNamingConvention());
-        
-        cfg.setSetting("naming_convention", "auto_detect");
-        assertEquals(NamingConvention.AUTO_DETECT, cfg.getNamingConvention());
-    }
-
-    public void testLazyImportsSetSetting() throws ConfigurationException {
-        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
-
-        assertFalse(cfgB.getLazyImports());
-        assertFalse(cfgB.isLazyImportsSet());
-        cfgB.setSetting("lazy_imports", "true");
-        assertTrue(cfgB.getLazyImports());
-        cfgB.setSetting("lazyImports", "false");
-        assertFalse(cfgB.getLazyImports());
-        assertTrue(cfgB.isLazyImportsSet());
-    }
-    
-    public void testLazyAutoImportsSetSetting() throws ConfigurationException {
-        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
-
-        assertNull(cfgB.getLazyAutoImports());
-        assertFalse(cfgB.isLazyAutoImportsSet());
-        cfgB.setSetting("lazy_auto_imports", "true");
-        assertEquals(Boolean.TRUE, cfgB.getLazyAutoImports());
-        assertTrue(cfgB.isLazyAutoImportsSet());
-        cfgB.setSetting("lazyAutoImports", "false");
-        assertEquals(Boolean.FALSE, cfgB.getLazyAutoImports());
-        cfgB.setSetting("lazyAutoImports", "null");
-        assertNull(cfgB.getLazyAutoImports());
-        assertTrue(cfgB.isLazyAutoImportsSet());
-        cfgB.unsetLazyAutoImports();
-        assertNull(cfgB.getLazyAutoImports());
-        assertFalse(cfgB.isLazyAutoImportsSet());
-    }
-
-    public void testLocaleSetting() throws TemplateException, ConfigurationException {
-        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
-
-        assertEquals(Locale.getDefault(), cfgB.getLocale());
-        assertFalse(cfgB.isLocaleSet());
-
-        Locale nonDefault = Locale.getDefault().equals(Locale.GERMANY) ? Locale.FRANCE : Locale.GERMANY;
-        cfgB.setLocale(nonDefault);
-        assertTrue(cfgB.isLocaleSet());
-        assertEquals(nonDefault, cfgB.getLocale());
-
-        cfgB.unsetLocale();
-        assertEquals(Locale.getDefault(), cfgB.getLocale());
-        assertFalse(cfgB.isLocaleSet());
-
-        cfgB.setSetting(Configuration.ExtendableBuilder.LOCALE_KEY, "JVM default");
-        assertEquals(Locale.getDefault(), cfgB.getLocale());
-        assertTrue(cfgB.isLocaleSet());
-    }
-
-    public void testDefaultEncodingSetting() throws TemplateException, ConfigurationException {
-        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
-
-        assertEquals(Charset.defaultCharset(), cfgB.getSourceEncoding());
-        assertFalse(cfgB.isSourceEncodingSet());
-
-        Charset nonDefault = Charset.defaultCharset().equals(StandardCharsets.UTF_8) ? StandardCharsets.ISO_8859_1
-                : StandardCharsets.UTF_8;
-        cfgB.setSourceEncoding(nonDefault);
-        assertTrue(cfgB.isSourceEncodingSet());
-        assertEquals(nonDefault, cfgB.getSourceEncoding());
-
-        cfgB.unsetSourceEncoding();
-        assertEquals(Charset.defaultCharset(), cfgB.getSourceEncoding());
-        assertFalse(cfgB.isSourceEncodingSet());
-
-        cfgB.setSetting(Configuration.ExtendableBuilder.SOURCE_ENCODING_KEY, "JVM default");
-        assertEquals(Charset.defaultCharset(), cfgB.getSourceEncoding());
-        assertTrue(cfgB.isSourceEncodingSet());
-    }
-
-    public void testTimeZoneSetting() throws TemplateException, ConfigurationException {
-        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
-
-        assertEquals(TimeZone.getDefault(), cfgB.getTimeZone());
-        assertFalse(cfgB.isTimeZoneSet());
-
-        TimeZone nonDefault = TimeZone.getDefault().equals(_DateUtil.UTC) ? TimeZone.getTimeZone("PST") : _DateUtil.UTC;
-        cfgB.setTimeZone(nonDefault);
-        assertTrue(cfgB.isTimeZoneSet());
-        assertEquals(nonDefault, cfgB.getTimeZone());
-
-        cfgB.unsetTimeZone();
-        assertEquals(TimeZone.getDefault(), cfgB.getTimeZone());
-        assertFalse(cfgB.isTimeZoneSet());
-
-        cfgB.setSetting(Configuration.ExtendableBuilder.TIME_ZONE_KEY, "JVM default");
-        assertEquals(TimeZone.getDefault(), cfgB.getTimeZone());
-        assertTrue(cfgB.isTimeZoneSet());
-    }
 
     @Test
     public void testGetSettingNamesAreSorted() throws Exception {
-        Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0).build();
         for (boolean camelCase : new boolean[] { false, true }) {
             List<String> names = new ArrayList<>(Configuration.Builder.getSettingNames(camelCase));
-            List<String> procCfgNames = new ArrayList<>(new Template(null, "", cfg)
-                    .createProcessingEnvironment(null, _NullWriter.INSTANCE)
-                    .getSettingNames(camelCase));
-            assertStartsWith(names, procCfgNames);
+            List<String> inheritedNames = new ArrayList<>(
+                    MutableParsingAndProcessingConfiguration.getSettingNames(camelCase));
+            assertStartsWith(names, inheritedNames);
             
             String prevName = null;
-            for (int i = procCfgNames.size(); i < names.size(); i++) {
+            for (int i = inheritedNames.size(); i < names.size(); i++) {
                 String name = names.get(i);
                 if (prevName != null) {
                     assertThat(name, greaterThan(prevName));
@@ -1282,33 +731,28 @@ public class ConfigurationTest extends TestCase {
     }
 
     @Test
-    @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE")
     public void testGetSettingNamesNameConventionsContainTheSame() throws Exception {
-        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
         MutableProcessingConfigurationTest.testGetSettingNamesNameConventionsContainTheSame(
-                new ArrayList<>(cfgB.getSettingNames(false)),
-                new ArrayList<>(cfgB.getSettingNames(true)));
+                new ArrayList<>(Configuration.Builder.getSettingNames(false)),
+                new ArrayList<>(Configuration.Builder.getSettingNames(true)));
     }
 
     @Test
-    @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE")
     public void testStaticFieldKeysCoverAllGetSettingNames() throws Exception {
-        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
-        List<String> names = new ArrayList<>(cfgB.getSettingNames(false));
-        List<String> cfgableNames = new ArrayList<>(cfgB.getSettingNames(false));
-        assertStartsWith(names, cfgableNames);
-        
-        for (int i = cfgableNames.size(); i < names.size(); i++) {
-            String name = names.get(i);
+        List<String> names = new ArrayList<>(Configuration.Builder.getSettingNames(false));
+        for (String name :  names) {
             assertTrue("No field was found for " + name, keyFieldExists(name));
         }
     }
     
     @Test
     public void testGetSettingNamesCoversAllStaticKeyFields() throws Exception {
-        Collection<String> names = new Configuration.Builder(Configuration.VERSION_3_0_0).getSettingNames(false);
+        Collection<String> names = Configuration.Builder.getSettingNames(false);
         
-        for (Class<? extends MutableProcessingConfiguration> cfgableClass : new Class[] { Configuration.class, MutableProcessingConfiguration.class }) {
+        for (Class<?> cfgableClass : new Class[] {
+                Configuration.class,
+                MutableParsingAndProcessingConfiguration.class,
+                MutableProcessingConfiguration.class }) {
             for (Field f : cfgableClass.getFields()) {
                 if (f.getName().endsWith("_KEY")) {
                     final Object name = f.get(null);
@@ -1324,18 +768,6 @@ public class ConfigurationTest extends TestCase {
     }
 
     @Test
-    public void testGetSettingNamesCoversAllSettingNames() throws Exception {
-        Collection<String> names = new Configuration.Builder(Configuration.VERSION_3_0_0).getSettingNames(false);
-        
-        for (Field f : MutableProcessingConfiguration.class.getFields()) {
-            if (f.getName().endsWith("_KEY")) {
-                final Object name = f.get(null);
-                assertTrue("Missing setting name: " + name, names.contains(name));
-            }
-        }
-    }
-
-    @Test
     public void testSetSettingSupportsBothNamingConventions() throws Exception {
         Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
         
@@ -1536,7 +968,7 @@ public class ConfigurationTest extends TestCase {
     private boolean keyFieldExists(String name) throws Exception {
         Field field;
         try {
-            field = Configuration.class.getField(name.toUpperCase() + "_KEY");
+            field = Configuration.ExtendableBuilder.class.getField(name.toUpperCase() + "_KEY");
         } catch (NoSuchFieldException e) {
             return false;
         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/a9038a8b/freemarker-core-test/src/test/java/org/apache/freemarker/core/MutableParsingAndProcessingConfigurationTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/MutableParsingAndProcessingConfigurationTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/MutableParsingAndProcessingConfigurationTest.java
new file mode 100644
index 0000000..689d600
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/MutableParsingAndProcessingConfigurationTest.java
@@ -0,0 +1,382 @@
+/*
+ * 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.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import java.lang.reflect.Field;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import org.apache.freemarker.core.outputformat.impl.HTMLOutputFormat;
+import org.apache.freemarker.core.outputformat.impl.UndefinedOutputFormat;
+import org.apache.freemarker.core.outputformat.impl.XMLOutputFormat;
+import org.apache.freemarker.core.util._DateUtil;
+import org.apache.freemarker.core.util._NullArgumentException;
+import org.junit.Test;
+
+public class MutableParsingAndProcessingConfigurationTest {
+
+    @Test
+    public void testSetAutoEscaping() throws Exception {
+        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+
+        assertEquals(AutoEscapingPolicy.ENABLE_IF_DEFAULT, cfgB.getAutoEscapingPolicy());
+
+        cfgB.setAutoEscapingPolicy(AutoEscapingPolicy.ENABLE_IF_SUPPORTED);
+        assertEquals(AutoEscapingPolicy.ENABLE_IF_SUPPORTED, cfgB.getAutoEscapingPolicy());
+
+        cfgB.setAutoEscapingPolicy(AutoEscapingPolicy.ENABLE_IF_DEFAULT);
+        assertEquals(AutoEscapingPolicy.ENABLE_IF_DEFAULT, cfgB.getAutoEscapingPolicy());
+
+        cfgB.setAutoEscapingPolicy(AutoEscapingPolicy.DISABLE);
+        assertEquals(AutoEscapingPolicy.DISABLE, cfgB.getAutoEscapingPolicy());
+
+        cfgB.setSetting(Configuration.ExtendableBuilder.AUTO_ESCAPING_POLICY_KEY_CAMEL_CASE, "enableIfSupported");
+        assertEquals(AutoEscapingPolicy.ENABLE_IF_SUPPORTED, cfgB.getAutoEscapingPolicy());
+
+        cfgB.setSetting(Configuration.ExtendableBuilder.AUTO_ESCAPING_POLICY_KEY_CAMEL_CASE, "enable_if_supported");
+        assertEquals(AutoEscapingPolicy.ENABLE_IF_SUPPORTED, cfgB.getAutoEscapingPolicy());
+
+        cfgB.setSetting(Configuration.ExtendableBuilder.AUTO_ESCAPING_POLICY_KEY_CAMEL_CASE, "enableIfDefault");
+        assertEquals(AutoEscapingPolicy.ENABLE_IF_DEFAULT, cfgB.getAutoEscapingPolicy());
+
+        cfgB.setSetting(Configuration.ExtendableBuilder.AUTO_ESCAPING_POLICY_KEY_CAMEL_CASE, "enable_if_default");
+        assertEquals(AutoEscapingPolicy.ENABLE_IF_DEFAULT, cfgB.getAutoEscapingPolicy());
+
+        cfgB.setSetting(Configuration.ExtendableBuilder.AUTO_ESCAPING_POLICY_KEY_CAMEL_CASE, "disable");
+        assertEquals(AutoEscapingPolicy.DISABLE, cfgB.getAutoEscapingPolicy());
+    }
+
+    @Test
+    public void testSetOutputFormat() throws Exception {
+        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+
+        assertEquals(UndefinedOutputFormat.INSTANCE, cfgB.getOutputFormat());
+        assertFalse(cfgB.isOutputFormatSet());
+
+        try {
+            cfgB.setOutputFormat(null);
+            fail();
+        } catch (_NullArgumentException e) {
+            // Expected
+        }
+
+        assertFalse(cfgB.isOutputFormatSet());
+
+        cfgB.setSetting(Configuration.ExtendableBuilder.OUTPUT_FORMAT_KEY_CAMEL_CASE, XMLOutputFormat.class.getSimpleName());
+        assertEquals(XMLOutputFormat.INSTANCE, cfgB.getOutputFormat());
+
+        cfgB.setSetting(Configuration.ExtendableBuilder.OUTPUT_FORMAT_KEY_SNAKE_CASE, HTMLOutputFormat.class.getSimpleName());
+        assertEquals(HTMLOutputFormat.INSTANCE, cfgB.getOutputFormat());
+
+        cfgB.unsetOutputFormat();
+        assertEquals(UndefinedOutputFormat.INSTANCE, cfgB.getOutputFormat());
+        assertFalse(cfgB.isOutputFormatSet());
+
+        cfgB.setOutputFormat(UndefinedOutputFormat.INSTANCE);
+        assertTrue(cfgB.isOutputFormatSet());
+        cfgB.setSetting(Configuration.ExtendableBuilder.OUTPUT_FORMAT_KEY_CAMEL_CASE, "default");
+        assertFalse(cfgB.isOutputFormatSet());
+
+        try {
+            cfgB.setSetting(Configuration.ExtendableBuilder.OUTPUT_FORMAT_KEY, "null");
+        } catch (InvalidSettingValueException e) {
+            assertThat(e.getCause().getMessage(), containsString(UndefinedOutputFormat.class.getSimpleName()));
+        }
+    }
+
+    @Test
+    public void testSetRecognizeStandardFileExtensions() throws Exception {
+        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+
+        assertTrue(cfgB.getRecognizeStandardFileExtensions());
+        assertFalse(cfgB.isRecognizeStandardFileExtensionsSet());
+
+        cfgB.setRecognizeStandardFileExtensions(false);
+        assertFalse(cfgB.getRecognizeStandardFileExtensions());
+        assertTrue(cfgB.isRecognizeStandardFileExtensionsSet());
+
+        cfgB.unsetRecognizeStandardFileExtensions();
+        assertTrue(cfgB.getRecognizeStandardFileExtensions());
+        assertFalse(cfgB.isRecognizeStandardFileExtensionsSet());
+
+        cfgB.setRecognizeStandardFileExtensions(true);
+        assertTrue(cfgB.getRecognizeStandardFileExtensions());
+        assertTrue(cfgB.isRecognizeStandardFileExtensionsSet());
+
+        cfgB.setSetting(Configuration.ExtendableBuilder.RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_CAMEL_CASE, "false");
+        assertFalse(cfgB.getRecognizeStandardFileExtensions());
+        assertTrue(cfgB.isRecognizeStandardFileExtensionsSet());
+
+        cfgB.setSetting(Configuration.ExtendableBuilder.RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY_SNAKE_CASE, "default");
+        assertTrue(cfgB.getRecognizeStandardFileExtensions());
+        assertFalse(cfgB.isRecognizeStandardFileExtensionsSet());
+    }
+
+    @Test
+    public void testSetTabSize() throws Exception {
+        String ftl = "${\t}";
+
+        try {
+            new Template(null, ftl,
+                    new Configuration.Builder(Configuration.VERSION_3_0_0).build());
+            fail();
+        } catch (ParseException e) {
+            assertEquals(9, e.getColumnNumber());
+        }
+
+        try {
+            new Template(null, ftl,
+                    new Configuration.Builder(Configuration.VERSION_3_0_0).tabSize(1).build());
+            fail();
+        } catch (ParseException e) {
+            assertEquals(4, e.getColumnNumber());
+        }
+
+        try {
+            new Configuration.Builder(Configuration.VERSION_3_0_0).tabSize(0);
+            fail();
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+
+        try {
+            new Configuration.Builder(Configuration.VERSION_3_0_0).tabSize(257);
+            fail();
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+    }
+
+    @Test
+    public void testTabSizeSetting() throws Exception {
+        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+        assertEquals(8, cfgB.getTabSize());
+        cfgB.setSetting(Configuration.ExtendableBuilder.TAB_SIZE_KEY_CAMEL_CASE, "4");
+        assertEquals(4, cfgB.getTabSize());
+        cfgB.setSetting(Configuration.ExtendableBuilder.TAB_SIZE_KEY_SNAKE_CASE, "1");
+        assertEquals(1, cfgB.getTabSize());
+
+        try {
+            cfgB.setSetting(Configuration.ExtendableBuilder.TAB_SIZE_KEY_SNAKE_CASE, "x");
+            fail();
+        } catch (ConfigurationException e) {
+            assertThat(e.getCause(), instanceOf(NumberFormatException.class));
+        }
+    }
+
+    @Test
+    public void testNamingConventionSetSetting() throws ConfigurationException {
+        Configuration.Builder cfg = new Configuration.Builder(Configuration.VERSION_3_0_0);
+
+        assertEquals(NamingConvention.AUTO_DETECT, cfg.getNamingConvention());
+
+        cfg.setSetting("naming_convention", "legacy");
+        assertEquals(NamingConvention.LEGACY, cfg.getNamingConvention());
+
+        cfg.setSetting("naming_convention", "camel_case");
+        assertEquals(NamingConvention.CAMEL_CASE, cfg.getNamingConvention());
+
+        cfg.setSetting("naming_convention", "auto_detect");
+        assertEquals(NamingConvention.AUTO_DETECT, cfg.getNamingConvention());
+    }
+
+    @Test
+    public void testLazyImportsSetSetting() throws ConfigurationException {
+        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+
+        assertFalse(cfgB.getLazyImports());
+        assertFalse(cfgB.isLazyImportsSet());
+        cfgB.setSetting("lazy_imports", "true");
+        assertTrue(cfgB.getLazyImports());
+        cfgB.setSetting("lazyImports", "false");
+        assertFalse(cfgB.getLazyImports());
+        assertTrue(cfgB.isLazyImportsSet());
+    }
+
+    @Test
+    public void testLazyAutoImportsSetSetting() throws ConfigurationException {
+        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+
+        assertNull(cfgB.getLazyAutoImports());
+        assertFalse(cfgB.isLazyAutoImportsSet());
+        cfgB.setSetting("lazy_auto_imports", "true");
+        assertEquals(Boolean.TRUE, cfgB.getLazyAutoImports());
+        assertTrue(cfgB.isLazyAutoImportsSet());
+        cfgB.setSetting("lazyAutoImports", "false");
+        assertEquals(Boolean.FALSE, cfgB.getLazyAutoImports());
+        cfgB.setSetting("lazyAutoImports", "null");
+        assertNull(cfgB.getLazyAutoImports());
+        assertTrue(cfgB.isLazyAutoImportsSet());
+        cfgB.unsetLazyAutoImports();
+        assertNull(cfgB.getLazyAutoImports());
+        assertFalse(cfgB.isLazyAutoImportsSet());
+    }
+
+    @Test
+    public void testLocaleSetting() throws TemplateException, ConfigurationException {
+        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+
+        assertEquals(Locale.getDefault(), cfgB.getLocale());
+        assertFalse(cfgB.isLocaleSet());
+
+        Locale nonDefault = Locale.getDefault().equals(Locale.GERMANY) ? Locale.FRANCE : Locale.GERMANY;
+        cfgB.setLocale(nonDefault);
+        assertTrue(cfgB.isLocaleSet());
+        assertEquals(nonDefault, cfgB.getLocale());
+
+        cfgB.unsetLocale();
+        assertEquals(Locale.getDefault(), cfgB.getLocale());
+        assertFalse(cfgB.isLocaleSet());
+
+        cfgB.setSetting(Configuration.ExtendableBuilder.LOCALE_KEY, "JVM default");
+        assertEquals(Locale.getDefault(), cfgB.getLocale());
+        assertTrue(cfgB.isLocaleSet());
+    }
+
+    @Test
+    public void testSourceEncodingSetting() throws TemplateException, ConfigurationException {
+        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+
+        assertEquals(Charset.defaultCharset(), cfgB.getSourceEncoding());
+        assertFalse(cfgB.isSourceEncodingSet());
+
+        Charset nonDefault = Charset.defaultCharset().equals(StandardCharsets.UTF_8) ? StandardCharsets.ISO_8859_1
+                : StandardCharsets.UTF_8;
+        cfgB.setSourceEncoding(nonDefault);
+        assertTrue(cfgB.isSourceEncodingSet());
+        assertEquals(nonDefault, cfgB.getSourceEncoding());
+
+        cfgB.unsetSourceEncoding();
+        assertEquals(Charset.defaultCharset(), cfgB.getSourceEncoding());
+        assertFalse(cfgB.isSourceEncodingSet());
+
+        cfgB.setSetting(Configuration.ExtendableBuilder.SOURCE_ENCODING_KEY, "JVM default");
+        assertEquals(Charset.defaultCharset(), cfgB.getSourceEncoding());
+        assertTrue(cfgB.isSourceEncodingSet());
+    }
+
+    @Test
+    public void testTimeZoneSetting() throws TemplateException, ConfigurationException {
+        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+
+        assertEquals(TimeZone.getDefault(), cfgB.getTimeZone());
+        assertFalse(cfgB.isTimeZoneSet());
+
+        TimeZone nonDefault = TimeZone.getDefault().equals(_DateUtil.UTC) ? TimeZone.getTimeZone("PST") : _DateUtil.UTC;
+        cfgB.setTimeZone(nonDefault);
+        assertTrue(cfgB.isTimeZoneSet());
+        assertEquals(nonDefault, cfgB.getTimeZone());
+
+        cfgB.unsetTimeZone();
+        assertEquals(TimeZone.getDefault(), cfgB.getTimeZone());
+        assertFalse(cfgB.isTimeZoneSet());
+
+        cfgB.setSetting(Configuration.ExtendableBuilder.TIME_ZONE_KEY, "JVM default");
+        assertEquals(TimeZone.getDefault(), cfgB.getTimeZone());
+        assertTrue(cfgB.isTimeZoneSet());
+    }
+
+    // ------------
+
+    @Test
+    public void testGetSettingNamesAreSorted() throws Exception {
+        for (boolean camelCase : new boolean[] { false, true }) {
+            List<String> names = new ArrayList<>(MutableParsingAndProcessingConfiguration.getSettingNames(camelCase));
+            List<String> inheritedNames = new ArrayList<>(MutableProcessingConfiguration.getSettingNames(camelCase));
+            assertStartsWith(names, inheritedNames);
+
+            String prevName = null;
+            for (int i = inheritedNames.size(); i < names.size(); i++) {
+                String name = names.get(i);
+                if (prevName != null) {
+                    assertThat(name, greaterThan(prevName));
+                }
+                prevName = name;
+            }
+        }
+    }
+
+    @Test
+    public void testGetSettingNamesNameConventionsContainTheSame() throws Exception {
+        MutableProcessingConfigurationTest.testGetSettingNamesNameConventionsContainTheSame(
+                new ArrayList<>(MutableParsingAndProcessingConfiguration.getSettingNames(false)),
+                new ArrayList<>(MutableParsingAndProcessingConfiguration.getSettingNames(true)));
+    }
+
+    @Test
+    public void testStaticFieldKeysCoverAllGetSettingNames() throws Exception {
+        List<String> names = new ArrayList<>(MutableParsingAndProcessingConfiguration.getSettingNames(false));
+        for (String name :  names) {
+            assertTrue("No field was found for " + name, keyFieldExists(name));
+        }
+    }
+
+    @Test
+    public void testGetSettingNamesCoversAllStaticKeyFields() throws Exception {
+        Collection<String> names = MutableParsingAndProcessingConfiguration.getSettingNames(false);
+
+        for (Class<?> cfgableClass : new Class[] {
+                MutableParsingAndProcessingConfiguration.class,
+                MutableProcessingConfiguration.class }) {
+            for (Field f : cfgableClass.getFields()) {
+                if (f.getName().endsWith("_KEY")) {
+                    final String name = (String) f.get(null);
+                    assertTrue("Missing setting name: " + name, names.contains(name));
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testKeyStaticFieldsHasAllVariationsAndCorrectFormat() throws IllegalArgumentException, IllegalAccessException {
+        MutableProcessingConfigurationTest.testKeyStaticFieldsHasAllVariationsAndCorrectFormat(
+                MutableParsingAndProcessingConfiguration.class);
+    }
+
+    @SuppressWarnings("boxing")
+    private void assertStartsWith(List<String> list, List<String> headList) {
+        int index = 0;
+        for (String name : headList) {
+            assertThat(index, lessThan(list.size()));
+            assertEquals(name, list.get(index));
+            index++;
+        }
+    }
+
+    private boolean keyFieldExists(String name) throws Exception {
+        Field field;
+        try {
+            field = MutableParsingAndProcessingConfiguration.class.getField(name.toUpperCase() + "_KEY");
+        } catch (NoSuchFieldException e) {
+            return false;
+        }
+        assertEquals(name, field.get(null));
+        return true;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/a9038a8b/freemarker-core-test/src/test/java/org/apache/freemarker/core/MutableProcessingConfigurationTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/MutableProcessingConfigurationTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/MutableProcessingConfigurationTest.java
index f780e9d..001f0bc 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/MutableProcessingConfigurationTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/MutableProcessingConfigurationTest.java
@@ -23,25 +23,34 @@ import static org.hamcrest.Matchers.*;
 import static org.junit.Assert.*;
 
 import java.io.IOException;
+import java.io.StringWriter;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TimeZone;
 
 import org.apache.freemarker.core.userpkg.BaseNTemplateNumberFormatFactory;
 import org.apache.freemarker.core.userpkg.EpochMillisDivTemplateDateFormatFactory;
 import org.apache.freemarker.core.userpkg.EpochMillisTemplateDateFormatFactory;
 import org.apache.freemarker.core.userpkg.HexTemplateNumberFormatFactory;
 import org.apache.freemarker.core.util._CollectionUtil;
+import org.apache.freemarker.core.util._DateUtil;
+import org.apache.freemarker.core.util._NullWriter;
 import org.apache.freemarker.core.util._StringUtil;
 import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory;
 import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory;
 import org.junit.Test;
 
+import com.google.common.collect.ImmutableMap;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
 public class MutableProcessingConfigurationTest {
 
     @Test
@@ -239,4 +248,309 @@ public class MutableProcessingConfigurationTest {
         }
     }
 
+    @Test
+    public void testSetTimeZone() throws ConfigurationException {
+        TimeZone origSysDefTZ = TimeZone.getDefault();
+        try {
+            TimeZone sysDefTZ = TimeZone.getTimeZone("GMT-01");
+            TimeZone.setDefault(sysDefTZ);
+
+            Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+            assertEquals(sysDefTZ, cfgB.getTimeZone());
+            cfgB.setSetting(MutableProcessingConfiguration.TIME_ZONE_KEY, "JVM default");
+            assertEquals(sysDefTZ, cfgB.getTimeZone());
+
+            TimeZone newSysDefTZ = TimeZone.getTimeZone("GMT+09");
+            TimeZone.setDefault(newSysDefTZ);
+            assertEquals(sysDefTZ, cfgB.getTimeZone());
+            cfgB.setSetting(MutableProcessingConfiguration.TIME_ZONE_KEY, "JVM default");
+            assertEquals(newSysDefTZ, cfgB.getTimeZone());
+        } finally {
+            TimeZone.setDefault(origSysDefTZ);
+        }
+    }
+
+    @Test
+    public void testSetSQLDateAndTimeTimeZone() throws ConfigurationException {
+        TimeZone origSysDefTZ = TimeZone.getDefault();
+        try {
+            TimeZone sysDefTZ = TimeZone.getTimeZone("GMT-01");
+            TimeZone.setDefault(sysDefTZ);
+
+            Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+            assertNull(cfgB.getSQLDateAndTimeTimeZone());
+
+            cfgB.setSQLDateAndTimeTimeZone(null);
+            assertNull(cfgB.getSQLDateAndTimeTimeZone());
+
+            cfgB.setSetting(MutableProcessingConfiguration.SQL_DATE_AND_TIME_TIME_ZONE_KEY, "JVM default");
+            assertEquals(sysDefTZ, cfgB.getSQLDateAndTimeTimeZone());
+
+            cfgB.setSetting(MutableProcessingConfiguration.SQL_DATE_AND_TIME_TIME_ZONE_KEY, "null");
+            assertNull(cfgB.getSQLDateAndTimeTimeZone());
+        } finally {
+            TimeZone.setDefault(origSysDefTZ);
+        }
+    }
+
+    @Test
+    public void testTimeZoneLayers() throws Exception {
+        TimeZone localTZ = TimeZone.getTimeZone("Europe/Brussels");
+
+        {
+            Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0).build();
+            Template t = new Template(null, "", cfg);
+            Environment env1 = t.createProcessingEnvironment(null, new StringWriter());
+            Environment env2 = t.createProcessingEnvironment(null, new StringWriter());
+
+            // cfg:
+            assertEquals(TimeZone.getDefault(), cfg.getTimeZone());
+            assertNull(cfg.getSQLDateAndTimeTimeZone());
+            // env:
+            assertEquals(TimeZone.getDefault(), env1.getTimeZone());
+            assertNull(env1.getSQLDateAndTimeTimeZone());
+            // env 2:
+            assertEquals(TimeZone.getDefault(), env2.getTimeZone());
+            assertNull(env2.getSQLDateAndTimeTimeZone());
+
+            env1.setSQLDateAndTimeTimeZone(_DateUtil.UTC);
+            // cfg:
+            assertEquals(TimeZone.getDefault(), cfg.getTimeZone());
+            assertNull(cfg.getSQLDateAndTimeTimeZone());
+            // env:
+            assertEquals(TimeZone.getDefault(), env1.getTimeZone());
+            assertEquals(_DateUtil.UTC, env1.getSQLDateAndTimeTimeZone());
+
+            env1.setTimeZone(localTZ);
+            // cfg:
+            assertEquals(TimeZone.getDefault(), cfg.getTimeZone());
+            assertNull(cfg.getSQLDateAndTimeTimeZone());
+            // env:
+            assertEquals(localTZ, env1.getTimeZone());
+            assertEquals(_DateUtil.UTC, env1.getSQLDateAndTimeTimeZone());
+            // env 2:
+            assertEquals(TimeZone.getDefault(), env2.getTimeZone());
+            assertNull(env2.getSQLDateAndTimeTimeZone());
+        }
+
+        {
+            TimeZone otherTZ1 = TimeZone.getTimeZone("GMT+05");
+            TimeZone otherTZ2 = TimeZone.getTimeZone("GMT+06");
+            Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0)
+                    .timeZone(otherTZ1)
+                    .sqlDateAndTimeTimeZone(otherTZ2)
+                    .build();
+
+            Template t = new Template(null, "", cfg);
+            Environment env1 = t.createProcessingEnvironment(null, new StringWriter());
+            Environment env2 = t.createProcessingEnvironment(null, new StringWriter());
+
+            env1.setTimeZone(localTZ);
+            env1.setSQLDateAndTimeTimeZone(_DateUtil.UTC);
+
+            // cfg:
+            assertEquals(otherTZ1, cfg.getTimeZone());
+            assertEquals(otherTZ2, cfg.getSQLDateAndTimeTimeZone());
+            // env:
+            assertEquals(localTZ, env1.getTimeZone());
+            assertEquals(_DateUtil.UTC, env1.getSQLDateAndTimeTimeZone());
+            // env 2:
+            assertEquals(otherTZ1, env2.getTimeZone());
+            assertEquals(otherTZ2, env2.getSQLDateAndTimeTimeZone());
+
+            try {
+                setTimeZoneToNull(env2);
+                fail();
+            } catch (IllegalArgumentException e) {
+                // expected
+            }
+            env2.setSQLDateAndTimeTimeZone(null);
+            assertEquals(otherTZ1, env2.getTimeZone());
+            assertNull(env2.getSQLDateAndTimeTimeZone());
+        }
+    }
+
+    @SuppressFBWarnings(value="NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS", justification="Expected to fail")
+    private void setTimeZoneToNull(Environment env2) {
+        env2.setTimeZone(null);
+    }
+
+    @Test
+    public void testSetLogTemplateExceptionsViaSetSettingAPI() throws ConfigurationException {
+        Configuration.Builder cfg = new Configuration.Builder(Configuration.VERSION_3_0_0);
+        assertFalse(cfg.getLogTemplateExceptions());
+        cfg.setSetting(MutableProcessingConfiguration.LOG_TEMPLATE_EXCEPTIONS_KEY, "true");
+        assertTrue(cfg.getLogTemplateExceptions());
+    }
+
+    @Test
+    public void testApiBuiltinEnabled() throws Exception {
+        try {
+            new Template(
+                    null, "${1?api}",
+                    new Configuration.Builder(Configuration.VERSION_3_0_0).build())
+                    .process(null, _NullWriter.INSTANCE);
+            fail();
+        } catch (TemplateException e) {
+            assertThat(e.getMessage(), containsString(MutableProcessingConfiguration.API_BUILTIN_ENABLED_KEY));
+        }
+
+        new Template(
+                null, "${m?api.hashCode()}",
+                new Configuration.Builder(Configuration.VERSION_3_0_0).apiBuiltinEnabled(true).build())
+                .process(Collections.singletonMap("m", new HashMap()), _NullWriter.INSTANCE);
+    }
+
+    @Test
+    @SuppressFBWarnings(value = "NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS ", justification = "Testing wrong args")
+    public void testSetCustomNumberFormat() throws Exception {
+        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+
+        try {
+            cfgB.setCustomNumberFormats(null);
+            fail();
+        } catch (IllegalArgumentException e) {
+            assertThat(e.getMessage(), containsString("null"));
+        }
+
+        try {
+            cfgB.setCustomNumberFormats(Collections.<String, TemplateNumberFormatFactory>singletonMap(
+                    "", HexTemplateNumberFormatFactory.INSTANCE));
+            fail();
+        } catch (IllegalArgumentException e) {
+            assertThat(e.getMessage(), containsString("0 length"));
+        }
+
+        try {
+            cfgB.setCustomNumberFormats(Collections.<String, TemplateNumberFormatFactory>singletonMap(
+                    "a_b", HexTemplateNumberFormatFactory.INSTANCE));
+            fail();
+        } catch (IllegalArgumentException e) {
+            assertThat(e.getMessage(), containsString("a_b"));
+        }
+
+        try {
+            cfgB.setCustomNumberFormats(Collections.<String, TemplateNumberFormatFactory>singletonMap(
+                    "a b", HexTemplateNumberFormatFactory.INSTANCE));
+            fail();
+        } catch (IllegalArgumentException e) {
+            assertThat(e.getMessage(), containsString("a b"));
+        }
+
+        try {
+            cfgB.setCustomNumberFormats(ImmutableMap.<String, TemplateNumberFormatFactory>of(
+                    "a", HexTemplateNumberFormatFactory.INSTANCE,
+                    "@wrong", HexTemplateNumberFormatFactory.INSTANCE));
+            fail();
+        } catch (IllegalArgumentException e) {
+            assertThat(e.getMessage(), containsString("@wrong"));
+        }
+
+        cfgB.setSetting(MutableProcessingConfiguration.CUSTOM_NUMBER_FORMATS_KEY_CAMEL_CASE,
+                "{ 'base': " + BaseNTemplateNumberFormatFactory.class.getName() + "() }");
+        assertEquals(
+                Collections.singletonMap("base", BaseNTemplateNumberFormatFactory.INSTANCE),
+                cfgB.getCustomNumberFormats());
+
+        cfgB.setSetting(MutableProcessingConfiguration.CUSTOM_NUMBER_FORMATS_KEY_SNAKE_CASE,
+                "{ "
+                        + "'base': " + BaseNTemplateNumberFormatFactory.class.getName() + "(), "
+                        + "'hex': " + HexTemplateNumberFormatFactory.class.getName() + "()"
+                        + " }");
+        assertEquals(
+                ImmutableMap.of(
+                        "base", BaseNTemplateNumberFormatFactory.INSTANCE,
+                        "hex", HexTemplateNumberFormatFactory.INSTANCE),
+                cfgB.getCustomNumberFormats());
+
+        cfgB.setSetting(MutableProcessingConfiguration.CUSTOM_NUMBER_FORMATS_KEY, "{}");
+        assertEquals(Collections.emptyMap(), cfgB.getCustomNumberFormats());
+
+        try {
+            cfgB.setSetting(MutableProcessingConfiguration.CUSTOM_NUMBER_FORMATS_KEY_CAMEL_CASE,
+                    "{ 'x': " + EpochMillisTemplateDateFormatFactory.class.getName() + "() }");
+            fail();
+        } catch (ConfigurationException e) {
+            assertThat(e.getCause().getMessage(), allOf(
+                    containsString(EpochMillisTemplateDateFormatFactory.class.getName()),
+                    containsString(TemplateNumberFormatFactory.class.getName())));
+        }
+    }
+
+    @SuppressFBWarnings(value="NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS", justification="We test failures")
+    @Test
+    public void testSetCustomDateFormat() throws Exception {
+        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+
+        try {
+            cfgB.setCustomDateFormats(null);
+            fail();
+        } catch (IllegalArgumentException e) {
+            assertThat(e.getMessage(), containsString("null"));
+        }
+
+        try {
+            cfgB.setCustomDateFormats(Collections.<String, TemplateDateFormatFactory>singletonMap(
+                    "", EpochMillisTemplateDateFormatFactory.INSTANCE));
+            fail();
+        } catch (IllegalArgumentException e) {
+            assertThat(e.getMessage(), containsString("0 length"));
+        }
+
+        try {
+            cfgB.setCustomDateFormats(Collections.<String, TemplateDateFormatFactory>singletonMap(
+                    "a_b", EpochMillisTemplateDateFormatFactory.INSTANCE));
+            fail();
+        } catch (IllegalArgumentException e) {
+            assertThat(e.getMessage(), containsString("a_b"));
+        }
+
+        try {
+            cfgB.setCustomDateFormats(Collections.<String, TemplateDateFormatFactory>singletonMap(
+                    "a b", EpochMillisTemplateDateFormatFactory.INSTANCE));
+            fail();
+        } catch (IllegalArgumentException e) {
+            assertThat(e.getMessage(), containsString("a b"));
+        }
+
+        try {
+            cfgB.setCustomDateFormats(ImmutableMap.<String, TemplateDateFormatFactory>of(
+                    "a", EpochMillisTemplateDateFormatFactory.INSTANCE,
+                    "@wrong", EpochMillisTemplateDateFormatFactory.INSTANCE));
+            fail();
+        } catch (IllegalArgumentException e) {
+            assertThat(e.getMessage(), containsString("@wrong"));
+        }
+
+        cfgB.setSetting(MutableProcessingConfiguration.CUSTOM_DATE_FORMATS_KEY_CAMEL_CASE,
+                "{ 'epoch': " + EpochMillisTemplateDateFormatFactory.class.getName() + "() }");
+        assertEquals(
+                Collections.singletonMap("epoch", EpochMillisTemplateDateFormatFactory.INSTANCE),
+                cfgB.getCustomDateFormats());
+
+        cfgB.setSetting(MutableProcessingConfiguration.CUSTOM_DATE_FORMATS_KEY_SNAKE_CASE,
+                "{ "
+                        + "'epoch': " + EpochMillisTemplateDateFormatFactory.class.getName() + "(), "
+                        + "'epochDiv': " + EpochMillisDivTemplateDateFormatFactory.class.getName() + "()"
+                        + " }");
+        assertEquals(
+                ImmutableMap.of(
+                        "epoch", EpochMillisTemplateDateFormatFactory.INSTANCE,
+                        "epochDiv", EpochMillisDivTemplateDateFormatFactory.INSTANCE),
+                cfgB.getCustomDateFormats());
+
+        cfgB.setSetting(MutableProcessingConfiguration.CUSTOM_DATE_FORMATS_KEY, "{}");
+        assertEquals(Collections.emptyMap(), cfgB.getCustomDateFormats());
+
+        try {
+            cfgB.setSetting(MutableProcessingConfiguration.CUSTOM_DATE_FORMATS_KEY_CAMEL_CASE,
+                    "{ 'x': " + HexTemplateNumberFormatFactory.class.getName() + "() }");
+            fail();
+        } catch (ConfigurationException e) {
+            assertThat(e.getCause().getMessage(), allOf(
+                    containsString(HexTemplateNumberFormatFactory.class.getName()),
+                    containsString(TemplateDateFormatFactory.class.getName())));
+        }
+    }
+
 }