freemarker-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ddek...@apache.org
Subject incubator-freemarker git commit: The objectWrapper setting can only be set on the Configuration level now, to avoid (future) complications. The objectWrapper setting's value, when set via Properties, doesn't support the value "restricted" anymore, instea
Date Mon, 12 Jun 2017 08:35:54 GMT
Repository: incubator-freemarker
Updated Branches:
  refs/heads/3 a9038a8b9 -> 52faf3e73


The objectWrapper setting can only be set on the Configuration level now, to avoid (future) complications. The objectWrapper setting's value, when set via Properties, doesn't support the value "restricted" anymore, instead "RestrictedObjectWrapper(3.0.0)" can be written.


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

Branch: refs/heads/3
Commit: 52faf3e73fa624d6e1d740894da81a86f098ec07
Parents: a9038a8
Author: ddekany <ddekany@apache.org>
Authored: Mon Jun 12 10:35:43 2017 +0200
Committer: ddekany <ddekany@apache.org>
Committed: Mon Jun 12 10:35:43 2017 +0200

----------------------------------------------------------------------
 FM3-CHANGE-LOG.txt                              |   5 +-
 .../freemarker/core/ConfigurationTest.java      | 130 ++++++++++---------
 .../core/ObjectBuilderSettingsTest.java         |   8 +-
 .../apache/freemarker/core/Configuration.java   |  88 +++++++++----
 .../org/apache/freemarker/core/Environment.java |  12 +-
 .../core/MutableProcessingConfiguration.java    |  81 +-----------
 .../core/ProcessingConfiguration.java           |  17 ---
 .../org/apache/freemarker/core/Template.java    |  14 +-
 .../freemarker/core/TemplateConfiguration.java  |  24 ----
 .../freemarker/core/TopLevelConfiguration.java  |  16 +++
 .../core/_ObjectBuilderSettingEvaluator.java    |   1 -
 .../core/debug/RmiDebuggedEnvironmentImpl.java  |   2 +-
 .../freemarker/servlet/FreemarkerServlet.java   |   6 +-
 13 files changed, 173 insertions(+), 231 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/52faf3e7/FM3-CHANGE-LOG.txt
----------------------------------------------------------------------
diff --git a/FM3-CHANGE-LOG.txt b/FM3-CHANGE-LOG.txt
index f8287c6..dbaef97 100644
--- a/FM3-CHANGE-LOG.txt
+++ b/FM3-CHANGE-LOG.txt
@@ -131,8 +131,9 @@ the FreeMarer 3 changelog here:
 - Java methods (when using DefaultObjectWrapper) won't be accessible as sequences anyore. That is, earlier, instead of
   obj.m(1), you could write obj.m[1]. This strange feature has led to some tricky cases, while almost nobody has
   utilized it.
-- SimpleObjectWrapper was renamed to RestrictedObjectWrapper, also the "simple" setting value was rename to
-  "restricted".
+- SimpleObjectWrapper was renamed to RestrictedObjectWrapper. When configuring with properties, the `simple` setting
+  value for the `objectWrapper` (`object_wrapper`) setting is not supported anymore, instead `RestrictedObjectWrapper(3.0.0)`
+  can be written.
 - Removed the global static final ObjectWrapper-s. It had a "few" consequences:
   - Standard TemplateModel implementations that can have an ObjectWrapper contrucor parameter don't allow null there anymore.
     Also, any constructor overloads where you cold omit the ObjectWrapper were removed (these were deprecated in FM2 too).

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/52faf3e7/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 58e7254..b06035e 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
@@ -19,6 +19,8 @@
 
 package org.apache.freemarker.core;
 
+import static org.apache.freemarker.core.Configuration.*;
+import static org.apache.freemarker.core.Configuration.ExtendableBuilder.*;
 import static org.apache.freemarker.test.hamcerst.Matchers.*;
 import static org.hamcrest.Matchers.*;
 import static org.junit.Assert.*;
@@ -93,7 +95,7 @@ public class ConfigurationTest {
 
     @Test
     public void testUnsetAndIsSet() throws Exception {
-        Configuration.ExtendableBuilder<?> cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+        Configuration.ExtendableBuilder<?> cfgB = new Builder(VERSION_3_0_0);
         
         assertFalse(cfgB.isLogTemplateExceptionsSet());
         assertFalse(cfgB.getLogTemplateExceptions());
@@ -110,11 +112,11 @@ public class ConfigurationTest {
             assertFalse(cfgB.getLogTemplateExceptions());
         }
 
-        DefaultObjectWrapper dow = new DefaultObjectWrapper.Builder(Configuration.VERSION_3_0_0).build();
+        DefaultObjectWrapper dow = new DefaultObjectWrapper.Builder(VERSION_3_0_0).build();
         assertFalse(cfgB.isObjectWrapperSet());
         assertSame(dow, cfgB.getObjectWrapper());
         //
-        RestrictedObjectWrapper ow = new RestrictedObjectWrapper.Builder(Configuration.VERSION_3_0_0).build();
+        RestrictedObjectWrapper ow = new RestrictedObjectWrapper.Builder(VERSION_3_0_0).build();
         cfgB.setObjectWrapper(ow);
         assertTrue(cfgB.isObjectWrapperSet());
         assertSame(ow, cfgB.getObjectWrapper());
@@ -197,7 +199,7 @@ public class ConfigurationTest {
 
     @Test
     public void testTemplateLoadingErrors() throws Exception {
-        Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0)
+        Configuration cfg = new Builder(VERSION_3_0_0)
                 .templateLoader(new ClassTemplateLoader(getClass(), "nosuchpackage"))
                 .build();
         try {
@@ -210,17 +212,17 @@ public class ConfigurationTest {
 
     @Test
     public void testVersion() {
-        Version v = Configuration.getVersion();
+        Version v = getVersion();
         assertTrue(v.intValue() >= _CoreAPI.VERSION_INT_3_0_0);
         
         try {
-            new Configuration.Builder(new Version(999, 1, 2));
+            new Builder(new Version(999, 1, 2));
         } catch (IllegalArgumentException e) {
             assertThat(e.getMessage(), containsString("upgrade"));
         }
         
         try {
-            new Configuration.Builder(new Version(2, 3, 0));
+            new Builder(new Version(2, 3, 0));
         } catch (IllegalArgumentException e) {
             assertThat(e.getMessage(), containsString("3.0.0"));
         }
@@ -229,7 +231,7 @@ public class ConfigurationTest {
     @Test
     public void testShowErrorTips() throws Exception {
         try {
-            Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0).build();
+            Configuration cfg = new Builder(VERSION_3_0_0).build();
             new Template(null, "${x}", cfg).process(null, _NullWriter.INSTANCE);
             fail();
         } catch (TemplateException e) {
@@ -237,7 +239,7 @@ public class ConfigurationTest {
         }
 
         try {
-            Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0).showErrorTips(false).build();
+            Configuration cfg = new Builder(VERSION_3_0_0).showErrorTips(false).build();
             new Template(null, "${x}", cfg).process(null, _NullWriter.INSTANCE);
             fail();
         } catch (TemplateException e) {
@@ -261,7 +263,7 @@ public class ConfigurationTest {
         tl.putTemplate(tHuFtl, "${1}".getBytes(StandardCharsets.UTF_8));
         tl.putTemplate(tUtf8Ftl, "<#ftl encoding='utf-8'>".getBytes(StandardCharsets.UTF_8));
 
-        Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0)
+        Configuration cfg = new Builder(VERSION_3_0_0)
                 .locale(Locale.GERMAN)
                 .sourceEncoding(StandardCharsets.ISO_8859_1)
                 .templateLoader(tl)
@@ -376,7 +378,7 @@ public class ConfigurationTest {
 
     @Test
     public void testTemplateResolverCache() throws Exception {
-        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+        Builder cfgB = new Builder(VERSION_3_0_0);
         
         CacheStorageWithGetSize cache = (CacheStorageWithGetSize) cfgB.getTemplateCacheStorage();
         assertEquals(0, cache.getSize());
@@ -405,7 +407,7 @@ public class ConfigurationTest {
         tl.putTemplate("b.ftl", "In b.ftl");
 
         {
-            Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0)
+            Configuration cfg = new Builder(VERSION_3_0_0)
                     .templateLoader(tl)
                     .templateNameFormat(DefaultTemplateNameFormatFM2.INSTANCE)
                     .build();
@@ -416,7 +418,7 @@ public class ConfigurationTest {
         }
         
         {
-            Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0)
+            Configuration cfg = new Builder(VERSION_3_0_0)
                     .templateLoader(tl)
                     .templateNameFormat(DefaultTemplateNameFormat.INSTANCE)
                     .build();
@@ -429,36 +431,36 @@ public class ConfigurationTest {
 
     @Test
     public void testTemplateNameFormatSetSetting() throws Exception {
-        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+        Builder cfgB = new Builder(VERSION_3_0_0);
         assertSame(DefaultTemplateNameFormatFM2.INSTANCE, cfgB.getTemplateNameFormat());
-        cfgB.setSetting(Configuration.ExtendableBuilder.TEMPLATE_NAME_FORMAT_KEY, "defAult_2_4_0");
+        cfgB.setSetting(TEMPLATE_NAME_FORMAT_KEY, "defAult_2_4_0");
         assertSame(DefaultTemplateNameFormat.INSTANCE, cfgB.getTemplateNameFormat());
-        cfgB.setSetting(Configuration.ExtendableBuilder.TEMPLATE_NAME_FORMAT_KEY, "defaUlt_2_3_0");
+        cfgB.setSetting(TEMPLATE_NAME_FORMAT_KEY, "defaUlt_2_3_0");
         assertSame(DefaultTemplateNameFormatFM2.INSTANCE, cfgB.getTemplateNameFormat());
         assertTrue(cfgB.isTemplateNameFormatSet());
-        cfgB.setSetting(Configuration.ExtendableBuilder.TEMPLATE_NAME_FORMAT_KEY, "defauLt");
+        cfgB.setSetting(TEMPLATE_NAME_FORMAT_KEY, "defauLt");
         assertFalse(cfgB.isTemplateNameFormatSet());
     }
 
     @Test
     public void testObjectWrapperSetSetting() throws Exception {
-        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+        Builder cfgB = new Builder(VERSION_3_0_0);
         {
-            cfgB.setSetting(MutableProcessingConfiguration.OBJECT_WRAPPER_KEY, "defAult");
-            DefaultObjectWrapper dow = new DefaultObjectWrapper.Builder(Configuration.VERSION_3_0_0).build();
+            cfgB.setSetting(OBJECT_WRAPPER_KEY, "defAult");
+            DefaultObjectWrapper dow = new DefaultObjectWrapper.Builder(VERSION_3_0_0).build();
             assertSame(dow, cfgB.getObjectWrapper());
-            assertEquals(Configuration.VERSION_3_0_0, dow.getIncompatibleImprovements());
+            assertEquals(VERSION_3_0_0, dow.getIncompatibleImprovements());
         }
         
         {
-            cfgB.setSetting(MutableProcessingConfiguration.OBJECT_WRAPPER_KEY, "restricted");
+            cfgB.setSetting(OBJECT_WRAPPER_KEY, "restricted");
             assertThat(cfgB.getObjectWrapper(), instanceOf(RestrictedObjectWrapper.class));
         }
     }
 
     @Test
     public void testTemplateLookupStrategyDefault() throws Exception {
-        Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0)
+        Configuration cfg = new Builder(VERSION_3_0_0)
                 .templateLoader(new ClassTemplateLoader(ConfigurationTest.class, ""))
                 .build();
         assertSame(DefaultTemplateLookupStrategy.INSTANCE, cfg.getTemplateLookupStrategy());
@@ -474,7 +476,7 @@ public class ConfigurationTest {
             }
         };
 
-        Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0)
+        Configuration cfg = new Builder(VERSION_3_0_0)
                 .templateLoader(new ClassTemplateLoader(ConfigurationTest.class, ""))
                 .templateLookupStrategy(myStrategy)
                 .build();
@@ -484,7 +486,7 @@ public class ConfigurationTest {
 
     @Test
     public void testSetTemplateConfigurations() throws Exception {
-        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+        Builder cfgB = new Builder(VERSION_3_0_0);
         assertNull(cfgB.getTemplateConfigurations());
 
         StringTemplateLoader tl = new StringTemplateLoader();
@@ -496,7 +498,7 @@ public class ConfigurationTest {
         
         cfgB.setTimeZone(TimeZone.getTimeZone("GMT+09"));
         
-        cfgB.setSetting(Configuration.ExtendableBuilder.TEMPLATE_CONFIGURATIONS_KEY,
+        cfgB.setSetting(TEMPLATE_CONFIGURATIONS_KEY,
                 "MergingTemplateConfigurationFactory("
                     + "FirstMatchTemplateConfigurationFactory("
                         + "ConditionalTemplateConfigurationFactory("
@@ -541,13 +543,13 @@ public class ConfigurationTest {
         }
         
         assertNotNull(cfgB.getTemplateConfigurations());
-        cfgB.setSetting(Configuration.ExtendableBuilder.TEMPLATE_CONFIGURATIONS_KEY, "null");
+        cfgB.setSetting(TEMPLATE_CONFIGURATIONS_KEY, "null");
         assertNull(cfgB.getTemplateConfigurations());
     }
 
     @Test
     public void testGetOutputFormatByName() throws Exception {
-        Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0).build();
+        Configuration cfg = new Builder(VERSION_3_0_0).build();
         
         assertSame(HTMLOutputFormat.INSTANCE, cfg.getOutputFormat(HTMLOutputFormat.INSTANCE.getName()));
         
@@ -601,11 +603,11 @@ public class ConfigurationTest {
 
     @Test
     public void testSetRegisteredCustomOutputFormats() throws Exception {
-        Configuration.Builder cfg = new Configuration.Builder(Configuration.VERSION_3_0_0);
+        Builder cfg = new Builder(VERSION_3_0_0);
         
         assertTrue(cfg.getRegisteredCustomOutputFormats().isEmpty());
         
-        cfg.setSetting(Configuration.ExtendableBuilder.REGISTERED_CUSTOM_OUTPUT_FORMATS_KEY_CAMEL_CASE,
+        cfg.setSetting(REGISTERED_CUSTOM_OUTPUT_FORMATS_KEY_CAMEL_CASE,
                 "[org.apache.freemarker.core.userpkg.CustomHTMLOutputFormat(), "
                 + "org.apache.freemarker.core.userpkg.DummyOutputFormat()]");
         assertEquals(
@@ -613,7 +615,7 @@ public class ConfigurationTest {
                 new ArrayList(cfg.getRegisteredCustomOutputFormats()));
         
         try {
-            cfg.setSetting(Configuration.ExtendableBuilder.REGISTERED_CUSTOM_OUTPUT_FORMATS_KEY_SNAKE_CASE, "[TemplateConfiguration()]");
+            cfg.setSetting(REGISTERED_CUSTOM_OUTPUT_FORMATS_KEY_SNAKE_CASE, "[TemplateConfiguration()]");
             fail();
         } catch (InvalidSettingValueException e) {
             assertThat(e.getMessage(), containsString(OutputFormat.class.getSimpleName()));
@@ -622,16 +624,16 @@ public class ConfigurationTest {
 
     @Test
     public void testSetICIViaSetSettingAPI() throws ConfigurationException {
-        Configuration.Builder cfg = new Configuration.Builder(Configuration.VERSION_3_0_0);
-        assertEquals(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS, cfg.getIncompatibleImprovements());
+        Builder cfg = new Builder(VERSION_3_0_0);
+        assertEquals(DEFAULT_INCOMPATIBLE_IMPROVEMENTS, cfg.getIncompatibleImprovements());
         // This is the only valid value ATM:
-        cfg.setSetting(Configuration.ExtendableBuilder.INCOMPATIBLE_IMPROVEMENTS_KEY, "3.0.0");
-        assertEquals(Configuration.VERSION_3_0_0, cfg.getIncompatibleImprovements());
+        cfg.setSetting(INCOMPATIBLE_IMPROVEMENTS_KEY, "3.0.0");
+        assertEquals(VERSION_3_0_0, cfg.getIncompatibleImprovements());
     }
 
     @Test
     public void testSharedVariables() throws TemplateException, IOException {
-        Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0)
+        Configuration cfg = new Builder(VERSION_3_0_0)
                 .sharedVariables(ImmutableMap.of(
                         "a", "aa",
                         "b", "bb",
@@ -663,7 +665,7 @@ public class ConfigurationTest {
 
     @Test
     public void testTemplateUpdateDelay() throws Exception {
-        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+        Builder cfgB = new Builder(VERSION_3_0_0);
 
         assertEquals(
                 DefaultTemplateResolver.DEFAULT_TEMPLATE_UPDATE_DELAY_MILLIS,
@@ -676,45 +678,45 @@ public class ConfigurationTest {
         assertEquals(100L, (Object) cfgB.getTemplateUpdateDelayMilliseconds());
         
         try {
-            cfgB.setSetting(Configuration.ExtendableBuilder.TEMPLATE_UPDATE_DELAY_KEY, "5");
+            cfgB.setSetting(TEMPLATE_UPDATE_DELAY_KEY, "5");
             assertEquals(5000L, (Object) cfgB.getTemplateUpdateDelayMilliseconds());
         } catch (InvalidSettingValueException e) {
             assertThat(e.getMessage(), containsStringIgnoringCase("unit must be specified"));
         }
-        cfgB.setSetting(Configuration.ExtendableBuilder.TEMPLATE_UPDATE_DELAY_KEY, "0");
+        cfgB.setSetting(TEMPLATE_UPDATE_DELAY_KEY, "0");
         assertEquals(0L, (Object) cfgB.getTemplateUpdateDelayMilliseconds());
         try {
-            cfgB.setSetting(Configuration.ExtendableBuilder.TEMPLATE_UPDATE_DELAY_KEY, "5 foo");
+            cfgB.setSetting(TEMPLATE_UPDATE_DELAY_KEY, "5 foo");
             assertEquals(5000L, (Object) cfgB.getTemplateUpdateDelayMilliseconds());
         } catch (InvalidSettingValueException e) {
             assertThat(e.getMessage(), containsStringIgnoringCase("\"foo\""));
         }
         
-        cfgB.setSetting(Configuration.ExtendableBuilder.TEMPLATE_UPDATE_DELAY_KEY, "3 ms");
+        cfgB.setSetting(TEMPLATE_UPDATE_DELAY_KEY, "3 ms");
         assertEquals(3L, (Object) cfgB.getTemplateUpdateDelayMilliseconds());
-        cfgB.setSetting(Configuration.ExtendableBuilder.TEMPLATE_UPDATE_DELAY_KEY, "4ms");
+        cfgB.setSetting(TEMPLATE_UPDATE_DELAY_KEY, "4ms");
         assertEquals(4L, (Object) cfgB.getTemplateUpdateDelayMilliseconds());
         
-        cfgB.setSetting(Configuration.ExtendableBuilder.TEMPLATE_UPDATE_DELAY_KEY, "3 s");
+        cfgB.setSetting(TEMPLATE_UPDATE_DELAY_KEY, "3 s");
         assertEquals(3000L, (Object) cfgB.getTemplateUpdateDelayMilliseconds());
-        cfgB.setSetting(Configuration.ExtendableBuilder.TEMPLATE_UPDATE_DELAY_KEY, "4s");
+        cfgB.setSetting(TEMPLATE_UPDATE_DELAY_KEY, "4s");
         assertEquals(4000L, (Object) cfgB.getTemplateUpdateDelayMilliseconds());
         
-        cfgB.setSetting(Configuration.ExtendableBuilder.TEMPLATE_UPDATE_DELAY_KEY, "3 m");
+        cfgB.setSetting(TEMPLATE_UPDATE_DELAY_KEY, "3 m");
         assertEquals(1000L * 60 * 3, (Object) cfgB.getTemplateUpdateDelayMilliseconds());
-        cfgB.setSetting(Configuration.ExtendableBuilder.TEMPLATE_UPDATE_DELAY_KEY, "4m");
+        cfgB.setSetting(TEMPLATE_UPDATE_DELAY_KEY, "4m");
         assertEquals(1000L * 60 * 4, (Object) cfgB.getTemplateUpdateDelayMilliseconds());
 
-        cfgB.setSetting(Configuration.ExtendableBuilder.TEMPLATE_UPDATE_DELAY_KEY, "1 h");
+        cfgB.setSetting(TEMPLATE_UPDATE_DELAY_KEY, "1 h");
         assertEquals(1000L * 60 * 60, (Object) cfgB.getTemplateUpdateDelayMilliseconds());
-        cfgB.setSetting(Configuration.ExtendableBuilder.TEMPLATE_UPDATE_DELAY_KEY, "2h");
+        cfgB.setSetting(TEMPLATE_UPDATE_DELAY_KEY, "2h");
         assertEquals(1000L * 60 * 60 * 2, (Object) cfgB.getTemplateUpdateDelayMilliseconds());
     }
 
     @Test
     public void testGetSettingNamesAreSorted() throws Exception {
         for (boolean camelCase : new boolean[] { false, true }) {
-            List<String> names = new ArrayList<>(Configuration.Builder.getSettingNames(camelCase));
+            List<String> names = new ArrayList<>(Builder.getSettingNames(camelCase));
             List<String> inheritedNames = new ArrayList<>(
                     MutableParsingAndProcessingConfiguration.getSettingNames(camelCase));
             assertStartsWith(names, inheritedNames);
@@ -733,13 +735,13 @@ public class ConfigurationTest {
     @Test
     public void testGetSettingNamesNameConventionsContainTheSame() throws Exception {
         MutableProcessingConfigurationTest.testGetSettingNamesNameConventionsContainTheSame(
-                new ArrayList<>(Configuration.Builder.getSettingNames(false)),
-                new ArrayList<>(Configuration.Builder.getSettingNames(true)));
+                new ArrayList<>(Builder.getSettingNames(false)),
+                new ArrayList<>(Builder.getSettingNames(true)));
     }
 
     @Test
     public void testStaticFieldKeysCoverAllGetSettingNames() throws Exception {
-        List<String> names = new ArrayList<>(Configuration.Builder.getSettingNames(false));
+        List<String> names = new ArrayList<>(Builder.getSettingNames(false));
         for (String name :  names) {
             assertTrue("No field was found for " + name, keyFieldExists(name));
         }
@@ -747,7 +749,7 @@ public class ConfigurationTest {
     
     @Test
     public void testGetSettingNamesCoversAllStaticKeyFields() throws Exception {
-        Collection<String> names = Configuration.Builder.getSettingNames(false);
+        Collection<String> names = Builder.getSettingNames(false);
         
         for (Class<?> cfgableClass : new Class[] {
                 Configuration.class,
@@ -764,16 +766,16 @@ public class ConfigurationTest {
     
     @Test
     public void testKeyStaticFieldsHasAllVariationsAndCorrectFormat() throws IllegalArgumentException, IllegalAccessException {
-        MutableProcessingConfigurationTest.testKeyStaticFieldsHasAllVariationsAndCorrectFormat(Configuration.ExtendableBuilder.class);
+        MutableProcessingConfigurationTest.testKeyStaticFieldsHasAllVariationsAndCorrectFormat(ExtendableBuilder.class);
     }
 
     @Test
     public void testSetSettingSupportsBothNamingConventions() throws Exception {
-        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+        Builder cfgB = new Builder(VERSION_3_0_0);
         
-        cfgB.setSetting(Configuration.ExtendableBuilder.SOURCE_ENCODING_KEY_CAMEL_CASE, StandardCharsets.UTF_16LE.name());
+        cfgB.setSetting(SOURCE_ENCODING_KEY_CAMEL_CASE, StandardCharsets.UTF_16LE.name());
         assertEquals(StandardCharsets.UTF_16LE, cfgB.getSourceEncoding());
-        cfgB.setSetting(Configuration.ExtendableBuilder.SOURCE_ENCODING_KEY_SNAKE_CASE, StandardCharsets.UTF_8.name());
+        cfgB.setSetting(SOURCE_ENCODING_KEY_SNAKE_CASE, StandardCharsets.UTF_8.name());
         assertEquals(StandardCharsets.UTF_8, cfgB.getSourceEncoding());
         
         for (String nameCC : cfgB.getSettingNames(true)) {
@@ -807,7 +809,7 @@ public class ConfigurationTest {
     
     @Test
     public void testGetSupportedBuiltInDirectiveNames() {
-        Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0).build();
+        Configuration cfg = new Builder(VERSION_3_0_0).build();
         
         Set<String> allNames = cfg.getSupportedBuiltInDirectiveNames(NamingConvention.AUTO_DETECT);
         Set<String> lNames = cfg.getSupportedBuiltInDirectiveNames(NamingConvention.LEGACY);
@@ -822,7 +824,7 @@ public class ConfigurationTest {
 
     @Test
     public void testGetSupportedBuiltInNames() {
-        Configuration cfg = new Configuration.Builder(Configuration.VERSION_3_0_0).build();
+        Configuration cfg = new Builder(VERSION_3_0_0).build();
         
         Set<String> allNames = cfg.getSupportedBuiltInNames(NamingConvention.AUTO_DETECT);
         Set<String> lNames = cfg.getSupportedBuiltInNames(NamingConvention.LEGACY);
@@ -847,7 +849,7 @@ public class ConfigurationTest {
     
     @Test
     public void testRemovedSettings() {
-        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+        Builder cfgB = new Builder(VERSION_3_0_0);
         try {
             cfgB.setSetting("classic_compatible", "true");
             fail();
@@ -864,7 +866,7 @@ public class ConfigurationTest {
 
     @Test
     public void testCanBeBuiltOnlyOnce() {
-        Configuration.Builder builder = new Configuration.Builder(Configuration.VERSION_3_0_0);
+        Builder builder = new Builder(VERSION_3_0_0);
         builder.build();
         try {
             builder.build();
@@ -876,7 +878,7 @@ public class ConfigurationTest {
 
     @Test
     public void testCollectionSettingMutability() throws IOException {
-        Configuration.Builder cb = new Configuration.Builder(Configuration.VERSION_3_0_0);
+        Builder cb = new Builder(VERSION_3_0_0);
 
         assertTrue(_CollectionUtil.isMapKnownToBeUnmodifiable(cb.getSharedVariables()));
         Map<String, Object> mutableValue = new HashMap<>();
@@ -968,7 +970,7 @@ public class ConfigurationTest {
     private boolean keyFieldExists(String name) throws Exception {
         Field field;
         try {
-            field = Configuration.ExtendableBuilder.class.getField(name.toUpperCase() + "_KEY");
+            field = ExtendableBuilder.class.getField(name.toUpperCase() + "_KEY");
         } catch (NoSuchFieldException e) {
             return false;
         }
@@ -989,7 +991,7 @@ public class ConfigurationTest {
             extends Configuration.ExtendableBuilder<ImpliedSettingValuesTestBuilder> {
 
         ImpliedSettingValuesTestBuilder() {
-            super(Configuration.VERSION_3_0_0);
+            super(VERSION_3_0_0);
         }
 
         @Override

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/52faf3e7/freemarker-core-test/src/test/java/org/apache/freemarker/core/ObjectBuilderSettingsTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/ObjectBuilderSettingsTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/ObjectBuilderSettingsTest.java
index 543473b..24fe972 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/ObjectBuilderSettingsTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/ObjectBuilderSettingsTest.java
@@ -360,7 +360,7 @@ public class ObjectBuilderSettingsTest {
         
         {
             Properties props = new Properties();
-            props.setProperty(MutableProcessingConfiguration.OBJECT_WRAPPER_KEY,
+            props.setProperty(Configuration.ExtendableBuilder.OBJECT_WRAPPER_KEY,
                     "org.apache.freemarker.core.model.impl.DefaultObjectWrapper(3.0.0)");
             props.setProperty(MutableProcessingConfiguration.ARITHMETIC_ENGINE_KEY,
                     "org.apache.freemarker.core.ObjectBuilderSettingsTest$DummyArithmeticEngine");
@@ -387,7 +387,7 @@ public class ObjectBuilderSettingsTest {
         
         {
             Properties props = new Properties();
-            props.setProperty(MutableProcessingConfiguration.OBJECT_WRAPPER_KEY, "defAult");
+            props.setProperty(Configuration.ExtendableBuilder.OBJECT_WRAPPER_KEY, "defAult");
             props.setProperty(MutableProcessingConfiguration.ARITHMETIC_ENGINE_KEY,
                     "org.apache.freemarker.core.ObjectBuilderSettingsTest$DummyArithmeticEngine(x = 1)");
             props.setProperty(MutableProcessingConfiguration.TEMPLATE_EXCEPTION_HANDLER_KEY,
@@ -409,7 +409,7 @@ public class ObjectBuilderSettingsTest {
 
         {
             Properties props = new Properties();
-            props.setProperty(MutableProcessingConfiguration.OBJECT_WRAPPER_KEY, "Default");
+            props.setProperty(Configuration.ExtendableBuilder.OBJECT_WRAPPER_KEY, "Default");
             props.setProperty(MutableProcessingConfiguration.ARITHMETIC_ENGINE_KEY, "bigdecimal");
             props.setProperty(MutableProcessingConfiguration.TEMPLATE_EXCEPTION_HANDLER_KEY, "rethrow");
             cfgB.setSettings(props);
@@ -422,7 +422,7 @@ public class ObjectBuilderSettingsTest {
         
         {
             Properties props = new Properties();
-            props.setProperty(MutableProcessingConfiguration.OBJECT_WRAPPER_KEY, "DefaultObjectWrapper(3.0.0)");
+            props.setProperty(Configuration.ExtendableBuilder.OBJECT_WRAPPER_KEY, "DefaultObjectWrapper(3.0.0)");
             cfgB.setSettings(props);
             assertEquals(DefaultObjectWrapper.class, cfgB.getObjectWrapper().getClass());
             assertEquals(

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/52faf3e7/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 2af8ae0..164c8f2 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
@@ -50,6 +50,7 @@ import org.apache.freemarker.core.model.TemplateMarkupOutputModel;
 import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.TemplateModelException;
 import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
+import org.apache.freemarker.core.model.impl.RestrictedObjectWrapper;
 import org.apache.freemarker.core.outputformat.MarkupOutputFormat;
 import org.apache.freemarker.core.outputformat.OutputFormat;
 import org.apache.freemarker.core.outputformat.UnregisteredOutputFormatException;
@@ -149,6 +150,7 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
             // Must be sorted alphabetically!
             ExtendableBuilder.INCOMPATIBLE_IMPROVEMENTS_KEY_SNAKE_CASE,
             ExtendableBuilder.LOCALIZED_TEMPLATE_LOOKUP_KEY_SNAKE_CASE,
+            ExtendableBuilder.OBJECT_WRAPPER_KEY_SNAKE_CASE,
             ExtendableBuilder.REGISTERED_CUSTOM_OUTPUT_FORMATS_KEY_SNAKE_CASE,
             ExtendableBuilder.SHARED_VARIABLES_KEY_SNAKE_CASE,
             ExtendableBuilder.TEMPLATE_CACHE_STORAGE_KEY_SNAKE_CASE,
@@ -163,6 +165,7 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
             // Must be sorted alphabetically!
             ExtendableBuilder.INCOMPATIBLE_IMPROVEMENTS_KEY_CAMEL_CASE,
             ExtendableBuilder.LOCALIZED_TEMPLATE_LOOKUP_KEY_CAMEL_CASE,
+            ExtendableBuilder.OBJECT_WRAPPER_KEY_CAMEL_CASE,
             ExtendableBuilder.REGISTERED_CUSTOM_OUTPUT_FORMATS_KEY_CAMEL_CASE,
             ExtendableBuilder.SHARED_VARIABLES_KEY_CAMEL_CASE,
             ExtendableBuilder.TEMPLATE_CACHE_STORAGE_KEY_CAMEL_CASE,
@@ -378,7 +381,7 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
                     new ArrayList<> (regCustOutputFormats));
         }
 
-        ObjectWrapper objectWrapper = builder.getObjectWrapper();
+        this.objectWrapper = builder.getObjectWrapper();
 
         {
             Map<String, Object> sharedVariables = _CollectionUtil.mergeImmutableMaps(builder
@@ -386,7 +389,16 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
 
             HashMap<String, TemplateModel> wrappedSharedVariables = new HashMap<>(
                     sharedVariables.size() * 4 / 3 + 1, 0.75f);
-            wrapAndPutSharedVariables(wrappedSharedVariables, sharedVariables, objectWrapper);
+            for (Entry<String, Object> ent : sharedVariables.entrySet()) {
+                try {
+                    wrappedSharedVariables.put(ent.getKey(), objectWrapper.wrap(ent.getValue()));
+                } catch (TemplateModelException e) {
+                    throw new InvalidSettingValueException(
+                            ExtendableBuilder.SHARED_VARIABLES_KEY, null, false,
+                            "Failed to wrap shared variable " + _StringUtil.jQuote(ent.getKey()),
+                            e);
+                }
+            }
 
             this.wrappedSharedVariables = wrappedSharedVariables;
             this.sharedVariables = Collections.unmodifiableMap(sharedVariables);
@@ -416,7 +428,6 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
         booleanFormat = builder.getBooleanFormat();
         templateExceptionHandler = builder.getTemplateExceptionHandler();
         arithmeticEngine = builder.getArithmeticEngine();
-        this.objectWrapper = objectWrapper;
         outputEncoding = builder.getOutputEncoding();
         urlEscapingCharset = builder.getURLEscapingCharset();
         autoFlush = builder.getAutoFlush();
@@ -508,25 +519,6 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
         }
     }
 
-    private <SelfT extends ExtendableBuilder<SelfT>> void wrapAndPutSharedVariables(
-            HashMap<String, TemplateModel> wrappedSharedVariables, Map<String, Object> rawSharedVariables,
-            ObjectWrapper objectWrapper) throws InvalidSettingValueException {
-        if (rawSharedVariables.isEmpty()) {
-            return;
-        }
-
-        for (Entry<String, Object> ent : rawSharedVariables.entrySet()) {
-            try {
-                wrappedSharedVariables.put(ent.getKey(), objectWrapper.wrap(ent.getValue()));
-            } catch (TemplateModelException e) {
-                throw new InvalidSettingValueException(
-                        ExtendableBuilder.SHARED_VARIABLES_KEY, null, false,
-                        "Failed to wrap shared variable " + _StringUtil.jQuote(ent.getKey()),
-                        e);
-            }
-        }
-    }
-
     @Override
     public TemplateExceptionHandler getTemplateExceptionHandler() {
         return templateExceptionHandler;
@@ -1704,6 +1696,13 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
         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 OBJECT_WRAPPER_KEY_SNAKE_CASE = "object_wrapper";
+        /** Modern, camel case ({@code likeThis}) variation of the setting name. */
+        public static final String OBJECT_WRAPPER_KEY_CAMEL_CASE = "objectWrapper";
+        /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
+        public static final String OBJECT_WRAPPER_KEY = OBJECT_WRAPPER_KEY_SNAKE_CASE;
+
+        /** 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;
@@ -1731,6 +1730,7 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
         private boolean localizedTemplateLookupSet;
         private Collection<OutputFormat> registeredCustomOutputFormats;
         private Map<String, Object> sharedVariables;
+        private ObjectWrapper objectWrapper;
 
         private boolean alreadyBuilt;
 
@@ -1903,6 +1903,17 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
                         setTemplateConfigurations((TemplateConfigurationFactory) _ObjectBuilderSettingEvaluator.eval(
                                 value, TemplateConfigurationFactory.class, false, _SettingEvaluationEnvironment.getCurrent()));
                     }
+                } else if (OBJECT_WRAPPER_KEY_SNAKE_CASE.equals(name)
+                        || OBJECT_WRAPPER_KEY_CAMEL_CASE.equals(name)) {
+                    if (DEFAULT_VALUE.equalsIgnoreCase(value)) {
+                        this.unsetObjectWrapper();
+                    } else if ("restricted".equalsIgnoreCase(value)) {
+                        // FM3 TODO should depend on IcI, but maybe the simplest is to remove this convenience value
+                        setObjectWrapper(new RestrictedObjectWrapper.Builder(Configuration.VERSION_3_0_0).build());
+                    } else {
+                        setObjectWrapper((ObjectWrapper) _ObjectBuilderSettingEvaluator.eval(
+                                value, ObjectWrapper.class, false, _SettingEvaluationEnvironment.getCurrent()));
+                    }
                 } else {
                     nameUnhandled = true;
                 }
@@ -2686,7 +2697,36 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
 
         private DefaultObjectWrapper cachedDefaultObjectWrapper;
 
+        /**
+         * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another
+         * {@link ProcessingConfiguration}).
+         */
+        public void unsetObjectWrapper() {
+            objectWrapper = null;
+        }
+
+        /**
+         * Fluent API equivalent of {@link #setObjectWrapper(ObjectWrapper)}
+         */
+        public SelfT objectWrapper(ObjectWrapper value) {
+            setObjectWrapper(value);
+            return self();
+        }
+
         @Override
+        public ObjectWrapper getObjectWrapper() {
+            return isObjectWrapperSet() ? objectWrapper : getDefaultObjectWrapper();
+        }
+
+        @Override
+        public boolean isObjectWrapperSet() {
+            return objectWrapper != null;
+        }
+
+        /**
+         * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value
+         * from another {@link ProcessingConfiguration}), or throws {@link CoreSettingValueNotSetException}.
+         */
         protected ObjectWrapper getDefaultObjectWrapper() {
             if (cachedDefaultObjectWrapper == null) {
                 // Note: This field is cleared by onIncompatibleImprovementsChanged
@@ -2696,9 +2736,9 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
             return cachedDefaultObjectWrapper;
         }
 
-        @Override
         public void setObjectWrapper(ObjectWrapper objectWrapper) {
-            super.setObjectWrapper(objectWrapper);
+            _NullArgumentException.check("objectWrapper", objectWrapper);
+            this.objectWrapper = objectWrapper;
             if (objectWrapper != cachedDefaultObjectWrapper) {
                 // Just to make it GC-able
                 cachedDefaultObjectWrapper = null;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/52faf3e7/freemarker-core/src/main/java/org/apache/freemarker/core/Environment.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/Environment.java b/freemarker-core/src/main/java/org/apache/freemarker/core/Environment.java
index 316bd00..8b14714 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/Environment.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/Environment.java
@@ -921,11 +921,6 @@ public final class Environment extends MutableProcessingConfiguration<Environmen
     }
 
     @Override
-    protected ObjectWrapper getDefaultObjectWrapper() {
-        return getMainTemplate().getObjectWrapper();
-    }
-
-    @Override
     public void setLocale(Locale locale) {
         Locale prevLocale = getLocale();
         super.setLocale(locale);
@@ -2900,6 +2895,13 @@ public final class Environment extends MutableProcessingConfiguration<Environmen
         return customState;
     }
 
+    /**
+     * Convenience method that simply delegates to {@link Configuration#getObjectWrapper()}.
+     */
+    public ObjectWrapper getObjectWrapper() {
+        return getConfiguration().getObjectWrapper();
+    }
+
     final class NestedElementTemplateDirectiveBody implements TemplateDirectiveBody {
 
         private final ASTElement[] childBuffer;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/52faf3e7/freemarker-core/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java b/freemarker-core/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java
index 98d927f..5a68436 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java
@@ -158,14 +158,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
     public static final String ARITHMETIC_ENGINE_KEY_CAMEL_CASE = "arithmeticEngine";
     /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
     public static final String ARITHMETIC_ENGINE_KEY = ARITHMETIC_ENGINE_KEY_SNAKE_CASE;
-    
-    /** Legacy, snake case ({@code like_this}) variation of the setting name. */
-    public static final String OBJECT_WRAPPER_KEY_SNAKE_CASE = "object_wrapper";
-    /** Modern, camel case ({@code likeThis}) variation of the setting name. */
-    public static final String OBJECT_WRAPPER_KEY_CAMEL_CASE = "objectWrapper";
-    /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
-    public static final String OBJECT_WRAPPER_KEY = OBJECT_WRAPPER_KEY_SNAKE_CASE;
-    
+
     /** Legacy, snake case ({@code like_this}) variation of the setting name. */
     public static final String BOOLEAN_FORMAT_KEY_SNAKE_CASE = "boolean_format";
     /** Modern, camel case ({@code likeThis}) variation of the setting name. */
@@ -268,7 +261,6 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
         LOG_TEMPLATE_EXCEPTIONS_KEY_SNAKE_CASE,
         NEW_BUILTIN_CLASS_RESOLVER_KEY_SNAKE_CASE,
         NUMBER_FORMAT_KEY_SNAKE_CASE,
-        OBJECT_WRAPPER_KEY_SNAKE_CASE,
         OUTPUT_ENCODING_KEY_SNAKE_CASE,
         SHOW_ERROR_TIPS_KEY_SNAKE_CASE,
         SQL_DATE_AND_TIME_TIME_ZONE_KEY_SNAKE_CASE,
@@ -296,7 +288,6 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
         LOG_TEMPLATE_EXCEPTIONS_KEY_CAMEL_CASE,
         NEW_BUILTIN_CLASS_RESOLVER_KEY_CAMEL_CASE,
         NUMBER_FORMAT_KEY_CAMEL_CASE,
-        OBJECT_WRAPPER_KEY_CAMEL_CASE,
         OUTPUT_ENCODING_KEY_CAMEL_CASE,
         SHOW_ERROR_TIPS_KEY_CAMEL_CASE,
         SQL_DATE_AND_TIME_TIME_ZONE_KEY_CAMEL_CASE,
@@ -317,7 +308,6 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
     private String booleanFormat;
     private TemplateExceptionHandler templateExceptionHandler;
     private ArithmeticEngine arithmeticEngine;
-    private ObjectWrapper objectWrapper;
     private Charset outputEncoding;
     private boolean outputEncodingSet;
     private Charset urlEscapingCharset;
@@ -940,47 +930,6 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
     }
 
     /**
-     * Setter pair of {@link #getObjectWrapper()}
-     */
-    public void setObjectWrapper(ObjectWrapper objectWrapper) {
-        _NullArgumentException.check("objectWrapper", objectWrapper);
-        this.objectWrapper = objectWrapper;
-    }
-
-    /**
-     * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another
-     * {@link ProcessingConfiguration}).
-     */
-    public void unsetObjectWrapper() {
-        objectWrapper = null;
-    }
-
-    /**
-     * Fluent API equivalent of {@link #setObjectWrapper(ObjectWrapper)}
-     */
-    public SelfT objectWrapper(ObjectWrapper value) {
-        setObjectWrapper(value);
-        return self();
-    }
-
-    @Override
-    public ObjectWrapper getObjectWrapper() {
-         return isObjectWrapperSet()
-                ? objectWrapper : getDefaultObjectWrapper();
-    }
-
-    /**
-     * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value
-     * from another {@link ProcessingConfiguration}), or throws {@link CoreSettingValueNotSetException}.
-     */
-    protected abstract ObjectWrapper getDefaultObjectWrapper();
-
-    @Override
-    public boolean isObjectWrapperSet() {
-        return objectWrapper != null;
-    }
-
-    /**
      * The setter pair of {@link #getOutputEncoding()}
      */
     public void setOutputEncoding(Charset outputEncoding) {
@@ -1476,7 +1425,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
     /**
      * Sets a FreeMarker setting by a name and string value. If you can configure FreeMarker directly with Java (or
      * other programming language), you should use the dedicated setter methods instead (like
-     * {@link #setObjectWrapper(ObjectWrapper)}. This meant to be used only when you get settings from somewhere
+     * {@link #setTimeZone(TimeZone)}. This meant to be used only when you get settings from somewhere
      * as {@link String}-{@link String} name-value pairs (typically, as a {@link Properties} object). Below you find an
      * overview of the settings available.
      * 
@@ -1521,15 +1470,14 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
      *       {@code "bigdecimal"}, {@code "conservative"}.
      *       
      *   <li><p>{@code "object_wrapper"}:
-     *       See {@link #setObjectWrapper(ObjectWrapper)}.
+     *       See {@link Configuration.Builder#setObjectWrapper(ObjectWrapper)}.
      *       <br>String value: If the value contains dot, then it's interpreted as an <a href="#fm_obe">object builder
      *       expression</a>, with the addition that {@link DefaultObjectWrapper}, {@link DefaultObjectWrapper} and
      *       {@link RestrictedObjectWrapper} can be referred without package name. For example, these strings are valid
-     *       values: {@code "DefaultObjectWrapper(3.0.0)"},
-     *       {@code "DefaultObjectWrapper(2.3.21, simpleMapWrapper=true)"}.
-     *       <br>If the value does not contain dot, then it must be one of these special values (case insensitive):
-     *       {@code "default"} means the default of {@link Configuration},
-     *       {@code "restricted"} means the a {@link RestrictedObjectWrapper} instance.
+     *       values: {@code "DefaultObjectWrapper(3.0.0)"}, {@code "RestrictedObjectWrapper(3.0.0)"}.
+     *       {@code "com.example.MyObjectWrapper(1, 2, someProperty=true, otherProperty=false)"}.
+     *       <br>It also accepts the special value (case insensitive) {@code "default"}.
+     *       <br>It also accepts the special value (case insensitive) {@code "default"}.
      *
      *   <li><p>{@code "number_format"}: See {@link #setNumberFormat(String)}.
      *   
@@ -1936,21 +1884,6 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
                     setArithmeticEngine((ArithmeticEngine) _ObjectBuilderSettingEvaluator.eval(
                             value, ArithmeticEngine.class, false, _SettingEvaluationEnvironment.getCurrent()));
                 }
-            } else if (OBJECT_WRAPPER_KEY_SNAKE_CASE.equals(name) || OBJECT_WRAPPER_KEY_CAMEL_CASE.equals(name)) {
-                if (DEFAULT_VALUE.equalsIgnoreCase(value)) {
-                    if (this instanceof Configuration.ExtendableBuilder) {
-                        this.unsetObjectWrapper();
-                    } else {
-                        // FM3 TODO should depend on IcI
-                        setObjectWrapper(new DefaultObjectWrapper.Builder(Configuration.VERSION_3_0_0).build());
-                    }
-                } else if ("restricted".equalsIgnoreCase(value)) {
-                    // FM3 TODO should depend on IcI
-                    setObjectWrapper(new RestrictedObjectWrapper.Builder(Configuration.VERSION_3_0_0).build());
-                } else {
-                    setObjectWrapper((ObjectWrapper) _ObjectBuilderSettingEvaluator.eval(
-                                    value, ObjectWrapper.class, false, _SettingEvaluationEnvironment.getCurrent()));
-                }
             } else if (BOOLEAN_FORMAT_KEY_SNAKE_CASE.equals(name) || BOOLEAN_FORMAT_KEY_CAMEL_CASE.equals(name)) {
                 setBooleanFormat(value);
             } else if (OUTPUT_ENCODING_KEY_SNAKE_CASE.equals(name) || OUTPUT_ENCODING_KEY_CAMEL_CASE.equals(name)) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/52faf3e7/freemarker-core/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java
index e04075b..7186f00 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java
@@ -32,9 +32,6 @@ import java.util.TimeZone;
 
 import org.apache.freemarker.core.arithmetic.ArithmeticEngine;
 import org.apache.freemarker.core.arithmetic.impl.BigDecimalArithmeticEngine;
-import org.apache.freemarker.core.model.ObjectWrapper;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
 import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory;
 import org.apache.freemarker.core.valueformat.TemplateNumberFormat;
 import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory;
@@ -445,20 +442,6 @@ public interface ProcessingConfiguration {
     boolean isArithmeticEngineSet();
 
     /**
-     * The object wrapper used to wrap objects to {@link TemplateModel}-s.
-     * Its {@link Configuration}-level default is a {@link DefaultObjectWrapper} with all its setting on default
-     * values, and {@code incompatibleImprovements} set to {@link Configuration#getIncompatibleImprovements()}.
-     */
-    ObjectWrapper getObjectWrapper();
-
-    /**
-     * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
-     * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
-     * an {@link CoreSettingValueNotSetException}.
-     */
-    boolean isObjectWrapperSet();
-
-    /**
      * Informs FreeMarker about the charset used for the output. As FreeMarker outputs character stream (not
      * byte stream), it's not aware of the output charset unless the software that encloses it tells it
      * with this setting. Some templates may use FreeMarker features that require this information.

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/52faf3e7/freemarker-core/src/main/java/org/apache/freemarker/core/Template.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/Template.java b/freemarker-core/src/main/java/org/apache/freemarker/core/Template.java
index 8113eb8..02680fa 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/Template.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/Template.java
@@ -490,7 +490,7 @@ public class Template implements ProcessingConfiguration, CustomStateScope {
     * @param dataModel the holder of the variables visible from all templates; see {@link #process(Object, Writer)} for
     *     more details.
     * @param wrapper The {@link ObjectWrapper} to use to wrap objects into {@link TemplateModel}
-    *     instances. Normally you left it {@code null}, in which case {@link MutableProcessingConfiguration#getObjectWrapper()} will be
+    *     instances. Normally you left it {@code null}, in which case {@link Configuration#getObjectWrapper()} will be
     *     used.
     * @param out The {@link Writer} where the output of the template will go; see {@link #process(Object, Writer)} for
     *     more details.
@@ -508,7 +508,7 @@ public class Template implements ProcessingConfiguration, CustomStateScope {
             dataModelHash = (TemplateHashModel) dataModel;
         } else {
             if (wrapper == null) {
-                wrapper = getObjectWrapper();
+                wrapper = getConfiguration().getObjectWrapper();
             }
 
             if (dataModel == null) {
@@ -947,16 +947,6 @@ public class Template implements ProcessingConfiguration, CustomStateScope {
     }
 
     @Override
-    public ObjectWrapper getObjectWrapper() {
-        return tCfg != null && tCfg.isObjectWrapperSet() ? tCfg.getObjectWrapper() : cfg.getObjectWrapper();
-    }
-
-    @Override
-    public boolean isObjectWrapperSet() {
-        return tCfg != null && tCfg.isObjectWrapperSet();
-    }
-
-    @Override
     public Charset getOutputEncoding() {
         return tCfg != null && tCfg.isOutputEncodingSet() ? tCfg.getOutputEncoding() : cfg.getOutputEncoding();
     }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/52faf3e7/freemarker-core/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java b/freemarker-core/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java
index 284ec6b..e7ca08a 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java
@@ -27,7 +27,6 @@ import java.util.Map;
 import java.util.TimeZone;
 
 import org.apache.freemarker.core.arithmetic.ArithmeticEngine;
-import org.apache.freemarker.core.model.ObjectWrapper;
 import org.apache.freemarker.core.outputformat.OutputFormat;
 import org.apache.freemarker.core.util.CommonBuilder;
 import org.apache.freemarker.core.util._CollectionUtil;
@@ -64,7 +63,6 @@ public final class TemplateConfiguration implements ParsingAndProcessingConfigur
     private final String booleanFormat;
     private final TemplateExceptionHandler templateExceptionHandler;
     private final ArithmeticEngine arithmeticEngine;
-    private final ObjectWrapper objectWrapper;
     private final Charset outputEncoding;
     private final boolean outputEncodingSet;
     private final Charset urlEscapingCharset;
@@ -105,7 +103,6 @@ public final class TemplateConfiguration implements ParsingAndProcessingConfigur
         booleanFormat = builder.isBooleanFormatSet() ? builder.getBooleanFormat() : null;
         templateExceptionHandler = builder.isTemplateExceptionHandlerSet() ? builder.getTemplateExceptionHandler() : null;
         arithmeticEngine = builder.isArithmeticEngineSet() ? builder.getArithmeticEngine() : null;
-        objectWrapper = builder.isObjectWrapperSet() ? builder.getObjectWrapper() : null;
         outputEncodingSet = builder.isOutputEncodingSet();
         outputEncoding = outputEncodingSet ? builder.getOutputEncoding() : null;
         urlEscapingCharsetSet = builder.isURLEscapingCharsetSet();
@@ -434,19 +431,6 @@ public final class TemplateConfiguration implements ParsingAndProcessingConfigur
     }
 
     @Override
-    public ObjectWrapper getObjectWrapper() {
-        if (!isObjectWrapperSet()) {
-            throw new CoreSettingValueNotSetException("objectWrapper");
-        }
-        return objectWrapper;
-    }
-
-    @Override
-    public boolean isObjectWrapperSet() {
-        return objectWrapper != null;
-    }
-
-    @Override
     public Charset getOutputEncoding() {
         if (!isOutputEncodingSet()) {
             throw new CoreSettingValueNotSetException("");
@@ -712,11 +696,6 @@ public final class TemplateConfiguration implements ParsingAndProcessingConfigur
         }
 
         @Override
-        protected ObjectWrapper getDefaultObjectWrapper() {
-            throw new CoreSettingValueNotSetException("objectWrapper");
-        }
-
-        @Override
         protected Charset getDefaultOutputEncoding() {
             throw new CoreSettingValueNotSetException("outputEncoding");
         }
@@ -842,9 +821,6 @@ public final class TemplateConfiguration implements ParsingAndProcessingConfigur
             if (tc.isNumberFormatSet()) {
                 setNumberFormat(tc.getNumberFormat());
             }
-            if (tc.isObjectWrapperSet()) {
-                setObjectWrapper(tc.getObjectWrapper());
-            }
             if (tc.isOutputEncodingSet()) {
                 setOutputEncoding(tc.getOutputEncoding());
             }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/52faf3e7/freemarker-core/src/main/java/org/apache/freemarker/core/TopLevelConfiguration.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/TopLevelConfiguration.java b/freemarker-core/src/main/java/org/apache/freemarker/core/TopLevelConfiguration.java
index 66d3495..1211e51 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/TopLevelConfiguration.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/TopLevelConfiguration.java
@@ -22,7 +22,9 @@ package org.apache.freemarker.core;
 import java.util.Collection;
 import java.util.Map;
 
+import org.apache.freemarker.core.model.ObjectWrapper;
 import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
 import org.apache.freemarker.core.outputformat.OutputFormat;
 import org.apache.freemarker.core.outputformat.impl.PlainTextOutputFormat;
 import org.apache.freemarker.core.outputformat.impl.UndefinedOutputFormat;
@@ -270,4 +272,18 @@ public interface TopLevelConfiguration extends ParsingAndProcessingConfiguration
      */
     boolean isRegisteredCustomOutputFormatsSet();
 
+    /**
+     * The object wrapper used to wrap objects to {@link TemplateModel}-s. The default is a
+     * {@link DefaultObjectWrapper} with all its setting on default values, and {@code incompatibleImprovements} set
+     * to {@link Configuration#getIncompatibleImprovements()}.
+     */
+    ObjectWrapper getObjectWrapper();
+
+    /**
+     * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+     * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+     * an {@link CoreSettingValueNotSetException}.
+     */
+    boolean isObjectWrapperSet();
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/52faf3e7/freemarker-core/src/main/java/org/apache/freemarker/core/_ObjectBuilderSettingEvaluator.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/_ObjectBuilderSettingEvaluator.java b/freemarker-core/src/main/java/org/apache/freemarker/core/_ObjectBuilderSettingEvaluator.java
index 627d36a..89cdfaf 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/_ObjectBuilderSettingEvaluator.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/_ObjectBuilderSettingEvaluator.java
@@ -658,7 +658,6 @@ public class _ObjectBuilderSettingEvaluator {
             SHORTHANDS = new HashMap/*<String,String>*/();
             
             addWithSimpleName(SHORTHANDS, DefaultObjectWrapper.class);
-            addWithSimpleName(SHORTHANDS, DefaultObjectWrapper.class);
             addWithSimpleName(SHORTHANDS, RestrictedObjectWrapper.class);
 
             addWithSimpleName(SHORTHANDS, TemplateConfiguration.class);

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/52faf3e7/freemarker-core/src/main/java/org/apache/freemarker/core/debug/RmiDebuggedEnvironmentImpl.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/debug/RmiDebuggedEnvironmentImpl.java b/freemarker-core/src/main/java/org/apache/freemarker/core/debug/RmiDebuggedEnvironmentImpl.java
index 38b1d0a..f23186c 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/debug/RmiDebuggedEnvironmentImpl.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/debug/RmiDebuggedEnvironmentImpl.java
@@ -169,7 +169,7 @@ class RmiDebuggedEnvironmentImpl extends RmiDebugModelImpl implements DebuggedEn
                 MutableProcessingConfiguration.BOOLEAN_FORMAT_KEY,
                 MutableProcessingConfiguration.LOCALE_KEY,
                 MutableProcessingConfiguration.NUMBER_FORMAT_KEY,
-                MutableProcessingConfiguration.OBJECT_WRAPPER_KEY,
+                Configuration.Builder.OBJECT_WRAPPER_KEY,
                 MutableProcessingConfiguration.TEMPLATE_EXCEPTION_HANDLER_KEY);
 
         final ProcessingConfiguration ProcessingConfiguration;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/52faf3e7/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
----------------------------------------------------------------------
diff --git a/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java b/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
index 9f4fac5..14e0ac2 100644
--- a/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
+++ b/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
@@ -543,7 +543,7 @@ public class FreemarkerServlet extends HttpServlet {
         
         // Process object_wrapper init-param out of order:
         String objectWrapperInitParamValue = getInitParameter(
-                MutableProcessingConfiguration.OBJECT_WRAPPER_KEY, DEPR_INITPARAM_OBJECT_WRAPPER);
+                Configuration.Builder.OBJECT_WRAPPER_KEY, DEPR_INITPARAM_OBJECT_WRAPPER);
         if (objectWrapperInitParamValue != null) {
             setObjectWrapperFromInitParam(cfgB, objectWrapperInitParamValue);
         }
@@ -578,7 +578,7 @@ public class FreemarkerServlet extends HttpServlet {
             
             try {
                 if (name.equals(DEPR_INITPARAM_OBJECT_WRAPPER)
-                        || name.equals(MutableProcessingConfiguration.OBJECT_WRAPPER_KEY)
+                        || name.equals(Configuration.Builder.OBJECT_WRAPPER_KEY)
                         || name.equals(INIT_PARAM_TEMPLATE_PATH)
                         || name.equals(Configuration.ExtendableBuilder.INCOMPATIBLE_IMPROVEMENTS_KEY)) {
                     // ignore: we have already processed these
@@ -1246,7 +1246,7 @@ public class FreemarkerServlet extends HttpServlet {
      */
     protected void setObjectWrapperFromInitParam(Configuration.ExtendableBuilder<?> cb, String initParamValue)
             throws ConfigurationException {
-        cb.setSetting(MutableProcessingConfiguration.OBJECT_WRAPPER_KEY, initParamValue);
+        cb.setSetting(Configuration.Builder.OBJECT_WRAPPER_KEY, initParamValue);
     }
 
     protected HttpRequestParametersHashModel createRequestParametersHashModel(HttpServletRequest request) {


Mime
View raw message