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 <[email protected]>
Authored: Mon Jun 12 10:35:43 2017 +0200
Committer: ddekany <[email protected]>
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) {

Reply via email to