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). In FM2, such overloads has used the global static 
default DefaltObjectWrapper, but that was removed.
- If the ObjectWrapper is not a DefaultObjectWrapper (or a subclass of it), 
`className?new(args)` will only accept 0 arguments. (Earlier we have fallen 
back to using the global static default DefaultObjectWrapper instance to handle 
argument unwrapping and overloaded constructors.) Note that ?new is only used 
to instantiate TemplateModel-s, typically, tempalte language 
functions/directives implemented in Java, and so they hardly ever has an 
argument.
- FreemarkerServlet now requires that the ObjectWrapper it uses implements 
ObjectWrapperAndUnwrapper. (Thus, the return type of 
FreemarerServlet.createDefaultObjectWrapper() has changed to 
ObjectWrapperAndUnwrapper.) The unwrapping functionality is required when 
calling JSP custom tags/functions, and in FreeMarker 2 this was worked around 
with using the global static default DefaultObjectWrapper when the 
ObjectWrapper wasn't an ObjectWrapperAndUnwrapper.


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

Branch: refs/heads/3
Commit: b4dfe5d248275a96cf1e0c44fe0c92cdc14d3eca
Parents: 83b4b77
Author: ddekany <[email protected]>
Authored: Wed Mar 1 21:56:37 2017 +0100
Committer: ddekany <[email protected]>
Committed: Fri Mar 3 21:18:15 2017 +0100

----------------------------------------------------------------------
 .../apache/freemarker/core/ASTDirRecurse.java   |   3 +-
 .../org/apache/freemarker/core/ASTDirVisit.java |   3 +-
 .../org/apache/freemarker/core/ASTElement.java  |  28 ----
 .../freemarker/core/ASTExpAddOrConcat.java      |   7 +-
 .../apache/freemarker/core/ASTExpDefault.java   |  10 +-
 .../freemarker/core/ASTExpDynamicKeyName.java   |   9 +-
 .../freemarker/core/ASTExpHashLiteral.java      |   9 +-
 .../freemarker/core/ASTExpListLiteral.java      |  10 +-
 .../freemarker/core/BuiltInsForNodes.java       |  12 +-
 .../core/BuiltInsForStringsBasic.java           |   9 +-
 .../freemarker/core/BuiltInsForStringsMisc.java |  25 +++-
 .../core/BuiltInsForStringsRegexp.java          |  17 ++-
 .../apache/freemarker/core/Configurable.java    |  10 +-
 .../apache/freemarker/core/Configuration.java   |   7 +-
 .../org/apache/freemarker/core/Environment.java |  24 ++--
 .../freemarker/core/NativeCollectionEx.java     |  73 ++++++++++
 .../apache/freemarker/core/NativeHashEx2.java   | 105 ++++++++++++++
 .../apache/freemarker/core/NativeSequence.java  |  73 ++++++++++
 .../core/NativeStringArraySequence.java         |  53 +++++++
 .../NativeStringCollectionCollectionEx.java     |  79 ++++++++++
 .../core/NativeStringListSequence.java          |  56 ++++++++
 .../core/debug/RmiDebuggedEnvironmentImpl.java  |   9 +-
 .../apache/freemarker/core/model/Constants.java |  14 +-
 .../core/model/GeneralPurposeNothing.java       |  10 +-
 .../core/model/TemplateCollectionModelEx.java   |   8 --
 .../core/model/WrappingTemplateModel.java       |  21 +--
 .../core/model/impl/CollectionAndSequence.java  |   3 +
 .../impl/DefaultNonListCollectionAdapter.java   |  17 +--
 .../core/model/impl/DefaultObjectWrapper.java   |   9 +-
 .../core/model/impl/SimpleCollection.java       |  36 +----
 .../freemarker/core/model/impl/SimpleHash.java  | 136 +-----------------
 .../core/model/impl/SimpleSequence.java         | 144 +------------------
 .../core/model/impl/_StaticObjectWrappers.java  |  42 ------
 .../freemarker/dom/JaxenXPathSupport.java       |   4 +-
 .../apache/freemarker/dom/NodeListModel.java    |  21 +--
 .../dom/NodeQueryResultItemObjectWrapper.java   |  92 ++++++++++++
 .../freemarker/servlet/FreemarkerServlet.java   |  44 +++---
 .../servlet/HttpRequestHashModel.java           |  13 +-
 .../servlet/HttpRequestParametersHashModel.java |  15 +-
 .../servlet/jsp/FreeMarkerPageContext.java      |  42 +-----
 .../freemarker/servlet/jsp/JspContextModel.java |  56 --------
 .../freemarker/servlet/jsp/JspTagModelBase.java |   9 +-
 src/manual/en_US/FM3-CHANGE-LOG.txt             |  14 +-
 .../freemarker/core/ConfigurationTest.java      |  19 ++-
 .../core/NewBiObjectWrapperRestrictionTest.java |  51 +++++++
 .../model/impl/DefaultObjectWrapperTest.java    |  19 ---
 .../servlet/jsp/RealServletContainertTest.java  |   3 +-
 .../test/templatesuite/TemplateTestCase.java    |  14 +-
 .../test/templatesuite/models/BooleanList1.java |  36 +----
 .../test/templatesuite/models/BooleanList2.java |   8 +-
 .../test/templatesuite/models/LegacyList.java   |  73 ----------
 .../test/templatesuite/models/MultiModel1.java  |  13 +-
 .../test/templatesuite/models/MultiModel4.java  |   8 +-
 .../test/templatesuite/models/MultiModel5.java  |   7 +-
 .../models/TransformHashWrapper.java            |   6 +-
 .../test/util/FullyCustomObjectWrapper.java     |  91 ++++++++++++
 56 files changed, 912 insertions(+), 817 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/ASTDirRecurse.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ASTDirRecurse.java 
b/src/main/java/org/apache/freemarker/core/ASTDirRecurse.java
index d335df5..b95b3fc 100644
--- a/src/main/java/org/apache/freemarker/core/ASTDirRecurse.java
+++ b/src/main/java/org/apache/freemarker/core/ASTDirRecurse.java
@@ -26,7 +26,6 @@ import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.TemplateNodeModel;
 import org.apache.freemarker.core.model.TemplateScalarModel;
 import org.apache.freemarker.core.model.TemplateSequenceModel;
-import org.apache.freemarker.core.model.impl.SimpleSequence;
 
 
 /**
@@ -56,7 +55,7 @@ final class ASTDirRecurse extends ASTDirective {
         }
         if (nss != null) {
             if (nss instanceof TemplateHashModel) {
-                SimpleSequence ss = new SimpleSequence(1);
+                NativeSequence ss = new NativeSequence(1);
                 ss.add(nss);
                 nss = ss;
             } else if (!(nss instanceof TemplateSequenceModel)) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/ASTDirVisit.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ASTDirVisit.java 
b/src/main/java/org/apache/freemarker/core/ASTDirVisit.java
index 56b5710..4a4023b 100644
--- a/src/main/java/org/apache/freemarker/core/ASTDirVisit.java
+++ b/src/main/java/org/apache/freemarker/core/ASTDirVisit.java
@@ -25,7 +25,6 @@ import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.TemplateNodeModel;
 import org.apache.freemarker.core.model.TemplateScalarModel;
 import org.apache.freemarker.core.model.TemplateSequenceModel;
-import org.apache.freemarker.core.model.impl.SimpleSequence;
 
 
 /**
@@ -55,7 +54,7 @@ final class ASTDirVisit extends ASTDirective {
         }
         if (nss != null) {
             if (nss instanceof Environment.Namespace) {
-                SimpleSequence ss = new SimpleSequence(1);
+                NativeSequence ss = new NativeSequence(1);
                 ss.add(nss);
                 nss = ss;
             } else if (!(nss instanceof TemplateSequenceModel)) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/ASTElement.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ASTElement.java 
b/src/main/java/org/apache/freemarker/core/ASTElement.java
index 6e2d0b3..a9cbfc0 100644
--- a/src/main/java/org/apache/freemarker/core/ASTElement.java
+++ b/src/main/java/org/apache/freemarker/core/ASTElement.java
@@ -23,9 +23,6 @@ import java.io.IOException;
 import java.util.Collections;
 import java.util.Enumeration;
 
-import org.apache.freemarker.core.model.TemplateNodeModel;
-import org.apache.freemarker.core.model.TemplateSequenceModel;
-import org.apache.freemarker.core.model.impl.SimpleSequence;
 import org.apache.freemarker.core.util._ArrayEnumeration;
 
 /**
@@ -144,31 +141,6 @@ abstract class ASTElement extends ASTNode {
 
     // Methods to implement TemplateNodeModel
 
-    public TemplateNodeModel getParentNode() {
-        // return parent;
-        return null;
-    }
-
-    public String getNodeNamespace() {
-        return null;
-    }
-
-    public String getNodeType() {
-        return "element";
-    }
-
-    public TemplateSequenceModel getChildNodes() {
-        if (childBuffer != null) {
-            final SimpleSequence seq = new SimpleSequence(childCount);
-            for (int i = 0; i < childCount; i++) {
-                seq.add(childBuffer[i]);
-            }
-            return seq;
-        } else {
-            return new SimpleSequence(0);
-        }
-    }
-
     public String getNodeName() {
         String className = getClass().getName();
         int shortNameOffset = className.lastIndexOf('.') + 1;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/ASTExpAddOrConcat.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ASTExpAddOrConcat.java 
b/src/main/java/org/apache/freemarker/core/ASTExpAddOrConcat.java
index 019cbf5..15e632a 100644
--- a/src/main/java/org/apache/freemarker/core/ASTExpAddOrConcat.java
+++ b/src/main/java/org/apache/freemarker/core/ASTExpAddOrConcat.java
@@ -36,7 +36,6 @@ import org.apache.freemarker.core.model.TemplateSequenceModel;
 import org.apache.freemarker.core.model.impl.CollectionAndSequence;
 import org.apache.freemarker.core.model.impl.SimpleNumber;
 import org.apache.freemarker.core.model.impl.SimpleScalar;
-import org.apache.freemarker.core.model.impl.SimpleSequence;
 
 /**
  * AST expression node: binary {@code +} operator. Note that this is treated 
separately from the other 4 arithmetic
@@ -275,7 +274,7 @@ final class ASTExpAddOrConcat extends ASTExpression {
         throws TemplateModelException {
             if (keys == null) {
                 HashSet keySet = new HashSet();
-                SimpleSequence keySeq = new SimpleSequence(32);
+                NativeSequence keySeq = new NativeSequence(32);
                 addKeys(keySet, keySeq, (TemplateHashModelEx) left);
                 addKeys(keySet, keySeq, (TemplateHashModelEx) right);
                 size = keySet.size();
@@ -283,7 +282,7 @@ final class ASTExpAddOrConcat extends ASTExpression {
             }
         }
 
-        private static void addKeys(Set set, SimpleSequence keySeq, 
TemplateHashModelEx hash)
+        private static void addKeys(Set set, NativeSequence keySeq, 
TemplateHashModelEx hash)
         throws TemplateModelException {
             TemplateModelIterator it = hash.keys().iterator();
             while (it.hasNext()) {
@@ -299,7 +298,7 @@ final class ASTExpAddOrConcat extends ASTExpression {
         private void initValues()
         throws TemplateModelException {
             if (values == null) {
-                SimpleSequence seq = new SimpleSequence(size());
+                NativeSequence seq = new NativeSequence(size());
                 // Note: size() invokes initKeys() if needed.
             
                 int ln = keys.size();

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/ASTExpDefault.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ASTExpDefault.java 
b/src/main/java/org/apache/freemarker/core/ASTExpDefault.java
index 1015845..b891374 100755
--- a/src/main/java/org/apache/freemarker/core/ASTExpDefault.java
+++ b/src/main/java/org/apache/freemarker/core/ASTExpDefault.java
@@ -20,19 +20,17 @@
 package org.apache.freemarker.core;
 
 
+import org.apache.freemarker.core.model.Constants;
 import org.apache.freemarker.core.model.TemplateCollectionModel;
 import org.apache.freemarker.core.model.TemplateHashModelEx;
 import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.TemplateScalarModel;
 import org.apache.freemarker.core.model.TemplateSequenceModel;
-import org.apache.freemarker.core.model.impl.SimpleCollection;
 
 /** {@code exp!defExp}, {@code (exp)!defExp} and the same two with {@code 
(exp)!}. */
 class ASTExpDefault extends ASTExpression {
        
-    private static final TemplateCollectionModel EMPTY_COLLECTION = new 
SimpleCollection(new java.util.ArrayList(0));
-    
-       static private class EmptyStringAndSequence 
+       static private class EmptyStringAndSequence
          implements TemplateScalarModel, TemplateSequenceModel, 
TemplateHashModelEx {
                @Override
         public String getAsString() {
@@ -56,11 +54,11 @@ class ASTExpDefault extends ASTExpression {
                }
                @Override
         public TemplateCollectionModel keys() {
-                       return EMPTY_COLLECTION;
+                       return Constants.EMPTY_COLLECTION;
                }
                @Override
         public TemplateCollectionModel values() {
-                       return EMPTY_COLLECTION;
+                       return Constants.EMPTY_COLLECTION;
                }
                
        }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/ASTExpDynamicKeyName.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ASTExpDynamicKeyName.java 
b/src/main/java/org/apache/freemarker/core/ASTExpDynamicKeyName.java
index dd9c45e..b904ce4 100644
--- a/src/main/java/org/apache/freemarker/core/ASTExpDynamicKeyName.java
+++ b/src/main/java/org/apache/freemarker/core/ASTExpDynamicKeyName.java
@@ -19,8 +19,6 @@
 
 package org.apache.freemarker.core;
 
-import java.util.ArrayList;
-
 import org.apache.freemarker.core.model.Constants;
 import org.apache.freemarker.core.model.TemplateHashModel;
 import org.apache.freemarker.core.model.TemplateModel;
@@ -28,7 +26,6 @@ import org.apache.freemarker.core.model.TemplateNumberModel;
 import org.apache.freemarker.core.model.TemplateScalarModel;
 import org.apache.freemarker.core.model.TemplateSequenceModel;
 import org.apache.freemarker.core.model.impl.SimpleScalar;
-import org.apache.freemarker.core.model.impl.SimpleSequence;
 
 /**
  * AST expression node: {@code target[keyExpression]}, where, in FM 2.3, 
{@code keyExpression} can be string, a number
@@ -211,14 +208,14 @@ final class ASTExpDynamicKeyName extends ASTExpression {
             return emptyResult(targetSeq != null);
         }
         if (targetSeq != null) {
-            ArrayList/*<TemplateModel>*/ list = new ArrayList(resultSize);
+            NativeSequence resultSeq = new NativeSequence(resultSize);
             int srcIdx = firstIdx;
             for (int i = 0; i < resultSize; i++) {
-                list.add(targetSeq.get(srcIdx));
+                resultSeq.add(targetSeq.get(srcIdx));
                 srcIdx += step;
             }
             // List items are already wrapped, so the wrapper will be null:
-            return new SimpleSequence(list, null);
+            return resultSeq;
         } else {
             final int exclEndIdx;
             if (step < 0 && resultSize > 1) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/ASTExpHashLiteral.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ASTExpHashLiteral.java 
b/src/main/java/org/apache/freemarker/core/ASTExpHashLiteral.java
index 369637a..50f8851 100644
--- a/src/main/java/org/apache/freemarker/core/ASTExpHashLiteral.java
+++ b/src/main/java/org/apache/freemarker/core/ASTExpHashLiteral.java
@@ -30,7 +30,6 @@ import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.TemplateModelException;
 import org.apache.freemarker.core.model.TemplateModelIterator;
 import org.apache.freemarker.core.model.impl.CollectionAndSequence;
-import org.apache.freemarker.core.model.impl.SimpleSequence;
 
 /**
  * AST expression node: <tt>{ keyExp: valueExp, ... }</tt> 
@@ -109,11 +108,11 @@ final class ASTExpHashLiteral extends ASTExpression {
 
     private class SequenceHash implements TemplateHashModelEx2 {
 
-        private HashMap map; // maps keys to integer offset
+        private HashMap<String, TemplateModel> map;
         private TemplateCollectionModel keyCollection, valueCollection; // 
ordered lists of keys and values
 
         SequenceHash(Environment env) throws TemplateException {
-            map = new LinkedHashMap();
+            map = new LinkedHashMap<>();
             for (int i = 0; i < size; i++) {
                 ASTExpression keyExp = (ASTExpression) keys.get(i);
                 ASTExpression valExp = (ASTExpression) values.get(i);
@@ -132,7 +131,7 @@ final class ASTExpHashLiteral extends ASTExpression {
         @Override
         public TemplateCollectionModel keys() {
             if (keyCollection == null) {
-                keyCollection = new CollectionAndSequence(new 
SimpleSequence(map.keySet()));
+                keyCollection = new CollectionAndSequence(new 
NativeStringCollectionCollectionEx(map.keySet()));
             }
             return keyCollection;
         }
@@ -140,7 +139,7 @@ final class ASTExpHashLiteral extends ASTExpression {
         @Override
         public TemplateCollectionModel values() {
             if (valueCollection == null) {
-                valueCollection = new CollectionAndSequence(new 
SimpleSequence(map.values()));
+                valueCollection = new CollectionAndSequence(new 
NativeCollectionEx(map.values()));
             }
             return valueCollection;
         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/ASTExpListLiteral.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ASTExpListLiteral.java 
b/src/main/java/org/apache/freemarker/core/ASTExpListLiteral.java
index b6af883..b3fba1f 100644
--- a/src/main/java/org/apache/freemarker/core/ASTExpListLiteral.java
+++ b/src/main/java/org/apache/freemarker/core/ASTExpListLiteral.java
@@ -22,7 +22,6 @@ package org.apache.freemarker.core;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
 
@@ -30,7 +29,6 @@ import org.apache.freemarker.core.model.TemplateMethodModel;
 import org.apache.freemarker.core.model.TemplateMethodModelEx;
 import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.TemplateSequenceModel;
-import org.apache.freemarker.core.model.impl.SimpleSequence;
 
 /**
  * AST expression node: {@code [ exp, ... ]} 
@@ -46,9 +44,9 @@ final class ASTExpListLiteral extends ASTExpression {
 
     @Override
     TemplateModel _eval(Environment env) throws TemplateException {
-        SimpleSequence list = new SimpleSequence(items.size());
-        for (Iterator it = items.iterator(); it.hasNext(); ) {
-            ASTExpression exp = (ASTExpression) it.next();
+        NativeSequence list = new NativeSequence(items.size());
+        for (Object item : items) {
+            ASTExpression exp = (ASTExpression) item;
             TemplateModel tm = exp.eval(env);
             exp.assertNonNull(tm, env);
             list.add(tm);
@@ -140,7 +138,7 @@ final class ASTExpListLiteral extends ASTExpression {
     // A hacky routine used by ASTDirVisit and ASTDirRecurse
     TemplateSequenceModel evaluateStringsToNamespaces(Environment env) throws 
TemplateException {
         TemplateSequenceModel val = (TemplateSequenceModel) eval(env);
-        SimpleSequence result = new SimpleSequence(val.size());
+        NativeSequence result = new NativeSequence(val.size());
         for (int i = 0; i < items.size(); i++) {
             Object itemExpr = items.get(i);
             if (itemExpr instanceof ASTExpStringLiteral) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/BuiltInsForNodes.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/BuiltInsForNodes.java 
b/src/main/java/org/apache/freemarker/core/BuiltInsForNodes.java
index b572deb..39bc546 100644
--- a/src/main/java/org/apache/freemarker/core/BuiltInsForNodes.java
+++ b/src/main/java/org/apache/freemarker/core/BuiltInsForNodes.java
@@ -27,11 +27,8 @@ import 
org.apache.freemarker.core.model.TemplateModelException;
 import org.apache.freemarker.core.model.TemplateNodeModel;
 import org.apache.freemarker.core.model.TemplateNodeModelEx;
 import org.apache.freemarker.core.model.impl.SimpleScalar;
-import org.apache.freemarker.core.model.impl.SimpleSequence;
 import org.apache.freemarker.core.util._StringUtil;
 
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-
 /**
  * A holder for builtins that operate exclusively on (XML-)node left-hand 
value.
  */
@@ -117,13 +114,14 @@ class BuiltInsForNodes {
     // Can't be instantiated
     private BuiltInsForNodes() { }
 
-    static class AncestorSequence extends SimpleSequence implements 
TemplateMethodModel {
-        
-        @SuppressFBWarnings(value="SE_BAD_FIELD",
-                justification="Can't make this Serializable, and not extending 
SimpleSequence would be non-BC.")
+    static class AncestorSequence extends NativeSequence implements 
TemplateMethodModel {
+
+        private static final int INITIAL_CAPACITY = 12;
+
         private Environment env;
         
         AncestorSequence(Environment env) {
+            super(INITIAL_CAPACITY);
             this.env = env;
         }
         

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/BuiltInsForStringsBasic.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/BuiltInsForStringsBasic.java 
b/src/main/java/org/apache/freemarker/core/BuiltInsForStringsBasic.java
index 279ecb6..bcf00c4 100644
--- a/src/main/java/org/apache/freemarker/core/BuiltInsForStringsBasic.java
+++ b/src/main/java/org/apache/freemarker/core/BuiltInsForStringsBasic.java
@@ -19,6 +19,7 @@
 
 package org.apache.freemarker.core;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.StringTokenizer;
 import java.util.regex.Matcher;
@@ -32,8 +33,6 @@ import 
org.apache.freemarker.core.model.TemplateModelException;
 import org.apache.freemarker.core.model.TemplateScalarModel;
 import org.apache.freemarker.core.model.impl.SimpleNumber;
 import org.apache.freemarker.core.model.impl.SimpleScalar;
-import org.apache.freemarker.core.model.impl.SimpleSequence;
-import org.apache.freemarker.core.model.impl._StaticObjectWrappers;
 import org.apache.freemarker.core.util._StringUtil;
 
 class BuiltInsForStringsBasic {
@@ -555,7 +554,7 @@ class BuiltInsForStringsBasic {
                     Pattern pattern = RegexpHelper.getPattern(splitString, 
(int) flags);
                     result = pattern.split(s);
                 } 
-                return 
_StaticObjectWrappers.DEFAULT_OBJECT_WRAPPER.wrap(result);
+                return new NativeStringArraySequence(result);
             }
         }
         
@@ -683,12 +682,12 @@ class BuiltInsForStringsBasic {
     static class word_listBI extends BuiltInForString {
         @Override
         TemplateModel calculateResult(String s, Environment env) {
-            SimpleSequence result = new SimpleSequence();
+            ArrayList<String> result = new ArrayList<>();
             StringTokenizer st = new StringTokenizer(s);
             while (st.hasMoreTokens()) {
                result.add(st.nextToken());
             }
-            return result;
+            return new  NativeStringListSequence(result);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java 
b/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java
index f79f882..d0deade 100644
--- a/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java
+++ b/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java
@@ -33,10 +33,9 @@ import 
org.apache.freemarker.core.model.TemplateModelException;
 import org.apache.freemarker.core.model.TemplateScalarModel;
 import org.apache.freemarker.core.model.TemplateSequenceModel;
 import org.apache.freemarker.core.model.TemplateTransformModel;
-import org.apache.freemarker.core.model.impl.SimpleNumber;
-import org.apache.freemarker.core.model.impl._StaticObjectWrappers;
 import org.apache.freemarker.core.model.impl.BeanModel;
 import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
+import org.apache.freemarker.core.model.impl.SimpleNumber;
 
 class BuiltInsForStringsMisc {
 
@@ -289,11 +288,23 @@ class BuiltInsForStringsMisc {
             @Override
             public Object exec(List arguments) throws TemplateModelException {
                 ObjectWrapper ow = env.getObjectWrapper();
-                DefaultObjectWrapper dow =
-                    ow instanceof DefaultObjectWrapper
-                    ? (DefaultObjectWrapper) ow
-                    : _StaticObjectWrappers.DEFAULT_OBJECT_WRAPPER;
-                return dow.newInstance(cl, arguments);
+                if (ow instanceof DefaultObjectWrapper) {
+                    return ((DefaultObjectWrapper) ow).newInstance(cl, 
arguments);
+                }
+
+                if (!arguments.isEmpty()) {
+                    throw new TemplateModelException(
+                            "className?new(args) only supports 0 arguments in 
the current configuration, because "
+                            + " the objectWrapper setting value is not a "
+                            + DefaultObjectWrapper.class.getName() +
+                            " (or its subclass).");
+                }
+                try {
+                    return cl.newInstance();
+                } catch (Exception e) {
+                    throw new TemplateModelException("Failed to instantiate "
+                            + cl.getName() + " with its parameterless 
constructor; see cause exception", e);
+                }
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/BuiltInsForStringsRegexp.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/BuiltInsForStringsRegexp.java 
b/src/main/java/org/apache/freemarker/core/BuiltInsForStringsRegexp.java
index 5c2ec8c..0420d64 100644
--- a/src/main/java/org/apache/freemarker/core/BuiltInsForStringsRegexp.java
+++ b/src/main/java/org/apache/freemarker/core/BuiltInsForStringsRegexp.java
@@ -33,7 +33,6 @@ import org.apache.freemarker.core.model.TemplateModelIterator;
 import org.apache.freemarker.core.model.TemplateScalarModel;
 import org.apache.freemarker.core.model.TemplateSequenceModel;
 import org.apache.freemarker.core.model.impl.SimpleScalar;
-import org.apache.freemarker.core.model.impl.SimpleSequence;
 import org.apache.freemarker.core.util._StringUtil;
 
 
@@ -50,7 +49,8 @@ class BuiltInsForStringsRegexp {
             if (targetModel instanceof RegexMatchModel) {
                 return ((RegexMatchModel) targetModel).getGroups();
             } else if (targetModel instanceof RegexMatchModel.MatchWithGroups) 
{
-                return ((RegexMatchModel.MatchWithGroups) 
targetModel).groupsSeq;
+                return new 
NativeStringArraySequence(((RegexMatchModel.MatchWithGroups) 
targetModel).groups);
+
             } else {
                 throw new UnexpectedTypeException(target, targetModel,
                         "regular expression matcher",
@@ -138,14 +138,14 @@ class BuiltInsForStringsRegexp {
     implements TemplateBooleanModel, TemplateCollectionModel, 
TemplateSequenceModel {
         static class MatchWithGroups implements TemplateScalarModel {
             final String matchedInputPart;
-            final SimpleSequence groupsSeq;
-            
+            final String[] groups;
+
             MatchWithGroups(String input, Matcher matcher) {
                 matchedInputPart = input.substring(matcher.start(), 
matcher.end());
                 final int grpCount = matcher.groupCount() + 1;
-                groupsSeq = new SimpleSequence(grpCount);
+                groups = new String[grpCount];
                 for (int i = 0; i < grpCount; i++) {
-                    groupsSeq.add(matcher.group(i));
+                    groups[i] = matcher.group(i);
                 }
             }
             
@@ -199,6 +199,11 @@ class BuiltInsForStringsRegexp {
                     @Override
                     public TemplateModel get(int i) throws 
TemplateModelException {
                         try {
+                            // Avoid IndexOutOfBoundsException:
+                            if (i > firedEntireInputMatcher.groupCount()) {
+                                return null;
+                            }
+
                             return new 
SimpleScalar(firedEntireInputMatcher.group(i));
                         } catch (Exception e) {
                             throw new _TemplateModelException(e, "Failed to 
read match group");

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/Configurable.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/Configurable.java 
b/src/main/java/org/apache/freemarker/core/Configurable.java
index a750e3d..122a3c0 100644
--- a/src/main/java/org/apache/freemarker/core/Configurable.java
+++ b/src/main/java/org/apache/freemarker/core/Configurable.java
@@ -47,7 +47,6 @@ import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
 import org.apache.freemarker.core.model.impl.DefaultObjectWrapperBuilder;
 import org.apache.freemarker.core.model.impl.RestrictedObjectWrapper;
-import org.apache.freemarker.core.model.impl._StaticObjectWrappers;
 import org.apache.freemarker.core.outputformat.OutputFormat;
 import org.apache.freemarker.core.outputformat.impl.HTMLOutputFormat;
 import org.apache.freemarker.core.outputformat.impl.PlainTextOutputFormat;
@@ -1809,11 +1808,8 @@ public class Configurable {
      *       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} (the 
default depends on the
-     *       {@code Configuration#Configuration(Version) 
incompatible_improvements}, but a bug existed in 2.3.21 where
-     *       that was ignored),
-     *       {@code "default_2_3_0"} (means {@link 
_StaticObjectWrappers#DEFAULT_OBJECT_WRAPPER})
-     *       {@code "restricted"} (means the deprecated {@link 
_StaticObjectWrappers#RESTRICTED_OBJECT_WRAPPER}
+     *       {@code "default"} means the default of {@link Configuration},
+     *       {@code "restricted"} means the a {@link RestrictedObjectWrapper} 
instance.
      *
      *   <li><p>{@code "number_format"}: See {@link #setNumberFormat(String)}.
      *   
@@ -2213,7 +2209,7 @@ public class Configurable {
                         
setObjectWrapper(Configuration.getDefaultObjectWrapper(Configuration.VERSION_3_0_0));
                     }
                 } else if ("restricted".equalsIgnoreCase(value)) {
-                    
setObjectWrapper(_StaticObjectWrappers.RESTRICTED_OBJECT_WRAPPER);
+                    setObjectWrapper(new 
RestrictedObjectWrapper(Configuration.VERSION_3_0_0));
                 } else {
                     setObjectWrapper((ObjectWrapper) 
_ObjectBuilderSettingEvaluator.eval(
                                     value, ObjectWrapper.class, false, 
_SettingEvaluationEnvironment.getCurrent()));

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/Configuration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/Configuration.java 
b/src/main/java/org/apache/freemarker/core/Configuration.java
index 6b256b6..4bf2eae 100644
--- a/src/main/java/org/apache/freemarker/core/Configuration.java
+++ b/src/main/java/org/apache/freemarker/core/Configuration.java
@@ -42,6 +42,7 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
 import org.apache.freemarker.core.model.ObjectWrapper;
+import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper;
 import org.apache.freemarker.core.model.TemplateHashModelEx;
 import org.apache.freemarker.core.model.TemplateMarkupOutputModel;
 import org.apache.freemarker.core.model.TemplateModel;
@@ -557,10 +558,6 @@ public class Configuration extends Configurable implements 
Cloneable, ParserConf
         return new DefaultSoftCacheStorage(); 
     }
     
-    static CacheStorage createDefaultCacheStorage(Version 
incompatibleImprovements) {
-        return createDefaultCacheStorage(incompatibleImprovements, null); 
-    }
-    
     private static class DefaultSoftCacheStorage extends SoftCacheStorage {
         // Nothing to override
     }
@@ -2709,7 +2706,7 @@ public class Configuration extends Configurable 
implements Cloneable, ParserConf
      * 
      * @since 2.3.21
      */
-    public static ObjectWrapper getDefaultObjectWrapper(Version 
incompatibleImprovements) {
+    public static ObjectWrapperAndUnwrapper getDefaultObjectWrapper(Version 
incompatibleImprovements) {
         return new 
DefaultObjectWrapperBuilder(incompatibleImprovements).build();
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/Environment.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/Environment.java 
b/src/main/java/org/apache/freemarker/core/Environment.java
index 78e06db..d6cfa91 100644
--- a/src/main/java/org/apache/freemarker/core/Environment.java
+++ b/src/main/java/org/apache/freemarker/core/Environment.java
@@ -57,7 +57,6 @@ import org.apache.freemarker.core.model.TemplateSequenceModel;
 import org.apache.freemarker.core.model.TemplateTransformModel;
 import org.apache.freemarker.core.model.TransformControl;
 import org.apache.freemarker.core.model.impl.SimpleHash;
-import org.apache.freemarker.core.model.impl.SimpleSequence;
 import 
org.apache.freemarker.core.templateresolver.MalformedTemplateNameException;
 import org.apache.freemarker.core.templateresolver.TemplateNameFormat;
 import org.apache.freemarker.core.templateresolver.TemplateResolver;
@@ -577,9 +576,9 @@ public final class Environment extends Configurable {
     void invokeNodeHandlerFor(TemplateNodeModel node, TemplateSequenceModel 
namespaces)
             throws TemplateException, IOException {
         if (nodeNamespaces == null) {
-            SimpleSequence ss = new SimpleSequence(1);
-            ss.add(currentNamespace);
-            nodeNamespaces = ss;
+            NativeSequence seq = new NativeSequence(1);
+            seq.add(currentNamespace);
+            nodeNamespaces = seq;
         }
         int prevNodeNamespaceIndex = nodeNamespaceIndex;
         String prevNodeName = currentNodeName;
@@ -705,9 +704,9 @@ public final class Environment extends Configurable {
             final Map namedArgs, final List positionalArgs) throws 
TemplateException {
         String catchAllParamName = macro.getCatchAll();
         if (namedArgs != null) {
-            final SimpleHash catchAllParamValue;
+            final NativeHashEx2 catchAllParamValue;
             if (catchAllParamName != null) {
-                catchAllParamValue = new SimpleHash((ObjectWrapper) null);
+                catchAllParamValue = new NativeHashEx2();
                 macroCtx.setLocalVar(catchAllParamName, catchAllParamValue);
             } else {
                 catchAllParamValue = null;
@@ -731,9 +730,9 @@ public final class Environment extends Configurable {
                 }
             }
         } else if (positionalArgs != null) {
-            final SimpleSequence catchAllParamValue;
+            final NativeSequence catchAllParamValue;
             if (catchAllParamName != null) {
-                catchAllParamValue = new SimpleSequence((ObjectWrapper) null);
+                catchAllParamValue = new NativeSequence(8);
                 macroCtx.setLocalVar(catchAllParamName, catchAllParamValue);
             } else {
                 catchAllParamValue = null;
@@ -2743,10 +2742,11 @@ public final class Environment extends Configurable {
         private Template template;
 
         Namespace() {
-            template = Environment.this.getMainTemplate();
+            this(Environment.this.getMainTemplate());
         }
 
         Namespace(Template template) {
+            super(Environment.this.getObjectWrapper());
             this.template = template;
         }
 
@@ -2886,12 +2886,6 @@ public final class Environment extends Configurable {
         }
 
         @Override
-        public Map toMap() throws TemplateModelException {
-            ensureInitializedTME();
-            return super.toMap();
-        }
-
-        @Override
         public String toString() {
             ensureInitializedRTE();
             return super.toString();

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/NativeCollectionEx.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/NativeCollectionEx.java 
b/src/main/java/org/apache/freemarker/core/NativeCollectionEx.java
new file mode 100644
index 0000000..5afa98a
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/core/NativeCollectionEx.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.core;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.apache.freemarker.core.model.ObjectWrapper;
+import org.apache.freemarker.core.model.TemplateCollectionModelEx;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.TemplateModelIterator;
+
+/**
+ * A collection where each items is already a {@link TemplateModel}, so no 
{@link ObjectWrapper} need to be specified.
+ */
+class NativeCollectionEx implements TemplateCollectionModelEx {
+
+    private final Collection<TemplateModel> collection;
+
+    public NativeCollectionEx(Collection<TemplateModel> collection) {
+        this.collection = collection;
+    }
+
+    @Override
+    public int size() {
+        return collection.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return collection.isEmpty();
+    }
+
+    @Override
+    public TemplateModelIterator iterator() throws TemplateModelException {
+        return new TemplateModelIterator() {
+
+            private final Iterator<TemplateModel> iterator = 
collection.iterator();
+
+            @Override
+            public TemplateModel next() throws TemplateModelException {
+                if (!iterator.hasNext()) {
+                    throw new TemplateModelException("The collection has no 
more items.");
+                }
+
+                return iterator.next();
+            }
+
+            @Override
+            public boolean hasNext() {
+                return iterator.hasNext();
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/NativeHashEx2.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/NativeHashEx2.java 
b/src/main/java/org/apache/freemarker/core/NativeHashEx2.java
new file mode 100644
index 0000000..7290c2f
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/core/NativeHashEx2.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.core;
+
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.freemarker.core.model.ObjectWrapper;
+import org.apache.freemarker.core.model.TemplateCollectionModel;
+import org.apache.freemarker.core.model.TemplateHashModelEx2;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.impl.SimpleScalar;
+
+/**
+ * A hash where each value is already a {@link TemplateModel}, so no {@link 
ObjectWrapper} need to be specified.
+ *
+ * <p>While this class allows adding items, doing so is not thread-safe, and 
thus only meant to be done during the
+ * initialization of the sequence.
+ */
+class NativeHashEx2 implements TemplateHashModelEx2 {
+
+    private final LinkedHashMap<String, TemplateModel> map;
+
+    public NativeHashEx2() {
+        this.map = new LinkedHashMap<>();
+    }
+
+    @Override
+    public int size() throws TemplateModelException {
+        return map.size();
+    }
+
+    @Override
+    public TemplateModel get(String key) throws TemplateModelException {
+        return map.get(key);
+    }
+
+    @Override
+    public boolean isEmpty() throws TemplateModelException {
+        return map.isEmpty();
+    }
+
+    @Override
+    public KeyValuePairIterator keyValuePairIterator() throws 
TemplateModelException {
+        return new KeyValuePairIterator() {
+            private final Iterator<Map.Entry<String, TemplateModel>> 
entrySetIterator = map.entrySet().iterator();
+
+            @Override
+            public boolean hasNext() throws TemplateModelException {
+                return entrySetIterator.hasNext();
+            }
+
+            @Override
+            public KeyValuePair next() throws TemplateModelException {
+                return new KeyValuePair() {
+                    private final Map.Entry<String, TemplateModel> entry = 
entrySetIterator.next();
+
+                    @Override
+                    public TemplateModel getKey() throws 
TemplateModelException {
+                        return new SimpleScalar(entry.getKey());
+                    }
+
+                    @Override
+                    public TemplateModel getValue() throws 
TemplateModelException {
+                        return entry.getValue();
+                    }
+                };
+            }
+        };
+    }
+
+    @Override
+    public TemplateCollectionModel keys() throws TemplateModelException {
+        return new NativeStringCollectionCollectionEx(map.keySet());
+    }
+
+    @Override
+    public TemplateCollectionModel values() throws TemplateModelException {
+        return new NativeCollectionEx(map.values());
+    }
+
+    public TemplateModel put(String key, TemplateModel value) {
+        return map.put(key, value);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/NativeSequence.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/NativeSequence.java 
b/src/main/java/org/apache/freemarker/core/NativeSequence.java
new file mode 100644
index 0000000..c27971a
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/core/NativeSequence.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.freemarker.core.model.ObjectWrapper;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.TemplateSequenceModel;
+
+/**
+ * A sequence where each items is already a {@link TemplateModel}, so no 
{@link ObjectWrapper} need to be specified.
+ *
+ * <p>While this class allows adding items, doing so is not thread-safe, and 
thus only meant to be done during the
+ * initialization of the sequence.
+ */
+class NativeSequence implements TemplateSequenceModel {
+
+    private final ArrayList<TemplateModel> items;
+
+    public NativeSequence(int capacity) {
+        items = new ArrayList<>(capacity);
+    }
+
+    /**
+     * Copies the collection
+     */
+    public NativeSequence(Collection<TemplateModel> items) {
+        this.items = new ArrayList<>(items.size());
+        this.items.addAll(items);
+    }
+
+    public void add(TemplateModel tm) {
+        items.add(tm);
+    }
+
+    public void addAll(Collection<TemplateModel> items) {
+        this.items.addAll(items);
+    }
+
+    public void clear() {
+        items.clear();
+    }
+
+    @Override
+    public TemplateModel get(int index) throws TemplateModelException {
+        return items.get(index);
+    }
+
+    @Override
+    public int size() throws TemplateModelException {
+        return items.size();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/NativeStringArraySequence.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/NativeStringArraySequence.java 
b/src/main/java/org/apache/freemarker/core/NativeStringArraySequence.java
new file mode 100644
index 0000000..96e9899
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/core/NativeStringArraySequence.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.core;
+
+import org.apache.freemarker.core.model.ObjectWrapper;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.TemplateSequenceModel;
+import org.apache.freemarker.core.model.impl.DefaultArrayAdapter;
+import org.apache.freemarker.core.model.impl.SimpleScalar;
+
+/**
+ * Adapts (not copies) a {@link String} array with on-the-fly wrapping of the 
items to {@link SimpleScalar}-s. The
+ * important difference to {@link DefaultArrayAdapter} is that it doesn't 
depend on an {@link ObjectWrapper}, which is
+ * needed to guarantee the behavior of some template language constructs. The 
important difference to
+ * {@link NativeSequence} is that it doesn't need upfront conversion to {@link 
TemplateModel}-s (performance).
+ */
+class NativeStringArraySequence implements TemplateSequenceModel {
+
+    private final String[] items;
+
+    public NativeStringArraySequence(String[] items) {
+        this.items = items;
+    }
+
+    @Override
+    public TemplateModel get(int index) throws TemplateModelException {
+        return index < items.length ? new SimpleScalar(items[index]) : null;
+    }
+
+    @Override
+    public int size() throws TemplateModelException {
+        return items.length;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/NativeStringCollectionCollectionEx.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/NativeStringCollectionCollectionEx.java
 
b/src/main/java/org/apache/freemarker/core/NativeStringCollectionCollectionEx.java
new file mode 100644
index 0000000..b2437e7
--- /dev/null
+++ 
b/src/main/java/org/apache/freemarker/core/NativeStringCollectionCollectionEx.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.core;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.apache.freemarker.core.model.ObjectWrapper;
+import org.apache.freemarker.core.model.TemplateCollectionModelEx;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.TemplateModelIterator;
+import org.apache.freemarker.core.model.impl.DefaultNonListCollectionAdapter;
+import org.apache.freemarker.core.model.impl.SimpleScalar;
+
+/**
+ * Adapts (not copies) a {@link Collection} of {@link String}-s with 
on-the-fly wrapping of the items to {@link
+ * SimpleScalar}-s. The important difference to {@link 
DefaultNonListCollectionAdapter} is that it doesn't depend on an
+ * {@link ObjectWrapper}, which is needed to guarantee the behavior of some 
template language constructs. The important
+ * difference to {@link NativeCollectionEx} is that it doesn't need upfront 
conversion to {@link TemplateModel}-s
+ * (performance).
+ */
+class NativeStringCollectionCollectionEx implements TemplateCollectionModelEx {
+
+    private final Collection<String> collection;
+
+    public NativeStringCollectionCollectionEx(Collection<String> collection) {
+        this.collection = collection;
+    }
+
+    @Override
+    public int size() {
+        return collection.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return collection.isEmpty();
+    }
+
+    @Override
+    public TemplateModelIterator iterator() throws TemplateModelException {
+        return new TemplateModelIterator() {
+
+            private final Iterator<String> iterator = collection.iterator();
+
+            @Override
+            public TemplateModel next() throws TemplateModelException {
+                if (!iterator.hasNext()) {
+                    throw new TemplateModelException("The collection has no 
more items.");
+                }
+
+                return new SimpleScalar(iterator.next());
+            }
+
+            @Override
+            public boolean hasNext() {
+                return iterator.hasNext();
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/NativeStringListSequence.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/NativeStringListSequence.java 
b/src/main/java/org/apache/freemarker/core/NativeStringListSequence.java
new file mode 100644
index 0000000..7846fd3
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/core/NativeStringListSequence.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.core;
+
+import java.util.List;
+
+import org.apache.freemarker.core.model.ObjectWrapper;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.TemplateSequenceModel;
+import org.apache.freemarker.core.model.impl.DefaultListAdapter;
+import org.apache.freemarker.core.model.impl.SimpleScalar;
+
+/**
+ * Adapts (not copies) a {@link List} of {@link String}-s with on-the-fly 
wrapping of the items to {@link
+ * SimpleScalar}-s. The important difference to {@link DefaultListAdapter} is 
that it doesn't depend on an {@link
+ * ObjectWrapper}, which is needed to guarantee the behavior of some template 
language constructs. The important
+ * difference to {@link NativeSequence} is that it doesn't need upfront 
conversion to {@link TemplateModel}-s
+ * (performance).
+ */
+class NativeStringListSequence implements TemplateSequenceModel {
+
+    private final List<String> items;
+
+    public NativeStringListSequence(List<String> items) {
+        this.items = items;
+    }
+
+    @Override
+    public TemplateModel get(int index) throws TemplateModelException {
+        return index < items.size() ? new SimpleScalar(items.get(index)) : 
null;
+    }
+
+    @Override
+    public int size() throws TemplateModelException {
+        return items.size();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/debug/RmiDebuggedEnvironmentImpl.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/debug/RmiDebuggedEnvironmentImpl.java
 
b/src/main/java/org/apache/freemarker/core/debug/RmiDebuggedEnvironmentImpl.java
index 3229c81..fbee3b1 100644
--- 
a/src/main/java/org/apache/freemarker/core/debug/RmiDebuggedEnvironmentImpl.java
+++ 
b/src/main/java/org/apache/freemarker/core/debug/RmiDebuggedEnvironmentImpl.java
@@ -40,6 +40,8 @@ import 
org.apache.freemarker.core.model.TemplateCollectionModel;
 import org.apache.freemarker.core.model.TemplateHashModelEx;
 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.DefaultObjectWrapperBuilder;
 import org.apache.freemarker.core.model.impl.SimpleCollection;
 import org.apache.freemarker.core.model.impl.SimpleScalar;
 import org.apache.freemarker.core.util.UndeclaredThrowableException;
@@ -55,6 +57,9 @@ class RmiDebuggedEnvironmentImpl extends RmiDebugModelImpl 
implements DebuggedEn
     private static long nextId = 1;
     private static Set remotes = new HashSet();
 
+    private static final DefaultObjectWrapper OBJECT_WRAPPER = new 
DefaultObjectWrapperBuilder(Configuration
+            .VERSION_3_0_0)
+            .build();
     
     private boolean stopped = false;
     private final long id;
@@ -129,7 +134,7 @@ class RmiDebuggedEnvironmentImpl extends RmiDebugModelImpl 
implements DebuggedEn
 
         @Override
         public TemplateCollectionModel keys() {
-            return new SimpleCollection(keySet());
+            return new SimpleCollection(keySet(), OBJECT_WRAPPER);
         }
 
         @Override
@@ -140,7 +145,7 @@ class RmiDebuggedEnvironmentImpl extends RmiDebugModelImpl 
implements DebuggedEn
             for (Iterator it = keys.iterator(); it.hasNext(); ) {
                 list.add(get((String) it.next()));
             }
-            return new SimpleCollection(list);
+            return new SimpleCollection(list, OBJECT_WRAPPER);
         }
 
         @Override

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/model/Constants.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/Constants.java 
b/src/main/java/org/apache/freemarker/core/model/Constants.java
index bab1f8c..268188d 100644
--- a/src/main/java/org/apache/freemarker/core/model/Constants.java
+++ b/src/main/java/org/apache/freemarker/core/model/Constants.java
@@ -62,9 +62,19 @@ public class Constants {
         
     }
 
-    public static final TemplateCollectionModel EMPTY_COLLECTION = new 
EmptyCollectionModel();
+    public static final TemplateCollectionModelEx EMPTY_COLLECTION = new 
EmptyCollectionExModel();
     
-    private static class EmptyCollectionModel implements 
TemplateCollectionModel, Serializable {
+    private static class EmptyCollectionExModel implements 
TemplateCollectionModelEx, Serializable {
+
+        @Override
+        public int size() throws TemplateModelException {
+            return 0;
+        }
+
+        @Override
+        public boolean isEmpty() throws TemplateModelException {
+            return true;
+        }
 
         @Override
         public TemplateModelIterator iterator() throws TemplateModelException {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/model/GeneralPurposeNothing.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/model/GeneralPurposeNothing.java 
b/src/main/java/org/apache/freemarker/core/model/GeneralPurposeNothing.java
index 7d105e9..da1c102 100644
--- a/src/main/java/org/apache/freemarker/core/model/GeneralPurposeNothing.java
+++ b/src/main/java/org/apache/freemarker/core/model/GeneralPurposeNothing.java
@@ -19,11 +19,8 @@
 
 package org.apache.freemarker.core.model;
 
-import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.freemarker.core.model.impl.SimpleCollection;
-
 /**
  * Singleton object representing nothing, used by ?if_exists built-in.
  * It is meant to be interpreted in the most sensible way possible in various 
contexts.
@@ -35,8 +32,6 @@ implements TemplateBooleanModel, TemplateScalarModel, 
TemplateSequenceModel, Tem
 
     public static final TemplateModel INSTANCE = new GeneralPurposeNothing();
       
-    private static final TemplateCollectionModel EMPTY_COLLECTION = new 
SimpleCollection(new ArrayList(0));
-
     private GeneralPurposeNothing() {
     }
 
@@ -77,11 +72,12 @@ implements TemplateBooleanModel, TemplateScalarModel, 
TemplateSequenceModel, Tem
     
     @Override
     public TemplateCollectionModel keys() {
-        return EMPTY_COLLECTION;
+        return Constants.EMPTY_COLLECTION;
     }
 
     @Override
     public TemplateCollectionModel values() {
-        return EMPTY_COLLECTION;
+        return Constants.EMPTY_COLLECTION;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/model/TemplateCollectionModelEx.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/model/TemplateCollectionModelEx.java 
b/src/main/java/org/apache/freemarker/core/model/TemplateCollectionModelEx.java
index 3de434c..92f0e3a 100644
--- 
a/src/main/java/org/apache/freemarker/core/model/TemplateCollectionModelEx.java
+++ 
b/src/main/java/org/apache/freemarker/core/model/TemplateCollectionModelEx.java
@@ -42,12 +42,4 @@ public interface TemplateCollectionModelEx extends 
TemplateCollectionModel {
      */
     boolean isEmpty() throws TemplateModelException;
 
-    /**
-     * Tells if a given value occurs in the collection, according the rules of 
the wrapped collection. As of 2.3.22,
-     * this interface is not yet utilized by FTL, and certainly it won't be 
earlier than 2.4.0. The usefulness of this
-     * method is questionable, as the equality rules of Java differs from that 
of FTL, hence, calling this won't be
-     * equivalent with {@code ?seq_contains(e)}.
-     */
-    boolean contains(TemplateModel item) throws TemplateModelException;
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/model/WrappingTemplateModel.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/model/WrappingTemplateModel.java 
b/src/main/java/org/apache/freemarker/core/model/WrappingTemplateModel.java
index 1dd981e..206d9d4 100644
--- a/src/main/java/org/apache/freemarker/core/model/WrappingTemplateModel.java
+++ b/src/main/java/org/apache/freemarker/core/model/WrappingTemplateModel.java
@@ -19,7 +19,7 @@
 
 package org.apache.freemarker.core.model;
 
-import org.apache.freemarker.core.model.impl._StaticObjectWrappers;
+import org.apache.freemarker.core.util._NullArgumentException;
 
 /**
  * Convenience base-class for containers that wrap their contained arbitrary 
Java objects into {@link TemplateModel}
@@ -28,27 +28,16 @@ import 
org.apache.freemarker.core.model.impl._StaticObjectWrappers;
 abstract public class WrappingTemplateModel {
 
     private final ObjectWrapper objectWrapper;
-    
-    /**
-     * Protected constructor that creates a new wrapping template model using
-     * the default object wrapper.
-     * 
-     * @deprecated Use {@link #WrappingTemplateModel(ObjectWrapper)} instead; 
this method uses the deprecated.
-     */
-    @Deprecated
-    protected WrappingTemplateModel() {
-        this(null);
-    }
 
     /**
      * Protected constructor that creates a new wrapping template model using 
the specified object wrapper.
      * 
      * @param objectWrapper the wrapper to use. Passing {@code null} to it
-     *     is allowed but deprecated. If {@code null} is passed, the 
deprecated default object wrapper
-     *     is used.
+     *     is allowed but deprecated. Not {@code null}.
      */
     protected WrappingTemplateModel(ObjectWrapper objectWrapper) {
-        this.objectWrapper = objectWrapper != null ? objectWrapper : 
_StaticObjectWrappers.DEFAULT_OBJECT_WRAPPER;
+        _NullArgumentException.check("objectWrapper", objectWrapper);
+        this.objectWrapper = objectWrapper;
     }
     
     /**
@@ -67,7 +56,7 @@ abstract public class WrappingTemplateModel {
      * wrap the passed object.
      */
     protected final TemplateModel wrap(Object obj) throws 
TemplateModelException {
-        return objectWrapper.wrap(obj);
+            return objectWrapper.wrap(obj);
     }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/model/impl/CollectionAndSequence.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/model/impl/CollectionAndSequence.java
 
b/src/main/java/org/apache/freemarker/core/model/impl/CollectionAndSequence.java
index 49e230f..7979981 100644
--- 
a/src/main/java/org/apache/freemarker/core/model/impl/CollectionAndSequence.java
+++ 
b/src/main/java/org/apache/freemarker/core/model/impl/CollectionAndSequence.java
@@ -22,6 +22,7 @@ package org.apache.freemarker.core.model.impl;
 import java.util.ArrayList;
 
 import org.apache.freemarker.core.model.TemplateCollectionModel;
+import org.apache.freemarker.core.model.TemplateCollectionModelEx;
 import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.TemplateModelException;
 import org.apache.freemarker.core.model.TemplateModelIterator;
@@ -68,6 +69,8 @@ final public class CollectionAndSequence implements 
TemplateCollectionModel, Tem
     public int size() throws TemplateModelException {
         if (sequence != null) {
             return sequence.size();
+        } else if (collection instanceof TemplateCollectionModelEx) {
+            return ((TemplateCollectionModelEx) collection).size();
         } else {
             initSequence();
             return data.size();

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/model/impl/DefaultNonListCollectionAdapter.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/model/impl/DefaultNonListCollectionAdapter.java
 
b/src/main/java/org/apache/freemarker/core/model/impl/DefaultNonListCollectionAdapter.java
index 66fc933..3b128fd 100644
--- 
a/src/main/java/org/apache/freemarker/core/model/impl/DefaultNonListCollectionAdapter.java
+++ 
b/src/main/java/org/apache/freemarker/core/model/impl/DefaultNonListCollectionAdapter.java
@@ -23,8 +23,6 @@ import java.io.Serializable;
 import java.util.Collection;
 import java.util.List;
 
-import org.apache.freemarker.core._DelayedShortClassName;
-import org.apache.freemarker.core._TemplateModelException;
 import org.apache.freemarker.core.model.AdapterTemplateModel;
 import org.apache.freemarker.core.model.ObjectWrapper;
 import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper;
@@ -60,7 +58,7 @@ public class DefaultNonListCollectionAdapter extends 
WrappingTemplateModel imple
      * @param collection
      *            The collection to adapt; can't be {@code null}.
      * @param wrapper
-     *            The {@link ObjectWrapper} used to wrap the items in the 
array. Has to be
+     *            The {@link ObjectWrapper} used to wrap the items in the 
collection. Has to be
      *            {@link ObjectWrapperAndUnwrapper} because of planned future 
features.
      */
     public static DefaultNonListCollectionAdapter adapt(Collection collection, 
ObjectWrapperWithAPISupport wrapper) {
@@ -98,19 +96,6 @@ public class DefaultNonListCollectionAdapter extends 
WrappingTemplateModel imple
     }
 
     @Override
-    public boolean contains(TemplateModel item) throws TemplateModelException {
-        Object itemPojo = ((ObjectWrapperAndUnwrapper) 
getObjectWrapper()).unwrap(item);
-        try {
-            return collection.contains(itemPojo);
-        } catch (ClassCastException e) {
-            throw new _TemplateModelException(e,
-                    "Failed to check if the collection contains the item. 
Probably the item's Java type, ",
-                    itemPojo != null ? new 
_DelayedShortClassName(itemPojo.getClass()) : "Null",
-                    ", doesn't match the type of (some of) the collection 
items; see cause exception.");
-        }
-    }
-
-    @Override
     public TemplateModel getAPI() throws TemplateModelException {
         return ((ObjectWrapperWithAPISupport) 
getObjectWrapper()).wrapAsAPI(collection);
     }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapper.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapper.java 
b/src/main/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapper.java
index 82b360a..f13caf5 100644
--- 
a/src/main/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapper.java
+++ 
b/src/main/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapper.java
@@ -84,7 +84,6 @@ import org.w3c.dom.Node;
  * JSR 133 and related literature). When used as part of {@link 
Configuration}, of course it's enough if that was safely
  * published and then left unmodified.
  */
-// TODO Get rid of unused stuff (including other clases in this package) 
coming from BeansWrapper.
 public class DefaultObjectWrapper implements RichObjectWrapper, 
WriteProtectable {
 
     private static final Logger LOG = _CoreLogs.OBJECT_WRAPPER;
@@ -168,7 +167,7 @@ public class DefaultObjectWrapper implements 
RichObjectWrapper, WriteProtectable
     private ObjectWrapper outerIdentity = this;
     private boolean methodsShadowItems = true;
     private boolean strict;  // initialized by PropertyAssignments.apply
-    @Deprecated // Only exists to keep some JUnit tests working...
+    @Deprecated // Only exists to keep some JUnit tests working... [FM3]
     private boolean useModelCache;
 
     private final Version incompatibleImprovements;
@@ -662,6 +661,9 @@ public class DefaultObjectWrapper implements 
RichObjectWrapper, WriteProtectable
         if (obj instanceof Number) {
             return new SimpleNumber((Number) obj);
         }
+        if (obj instanceof Boolean) {
+            return obj.equals(Boolean.TRUE) ? TemplateBooleanModel.TRUE : 
TemplateBooleanModel.FALSE;
+        }
         if (obj instanceof java.util.Date) {
             if (obj instanceof java.sql.Date) {
                 return new SimpleDate((java.sql.Date) obj);
@@ -686,9 +688,6 @@ public class DefaultObjectWrapper implements 
RichObjectWrapper, WriteProtectable
         if (obj instanceof Map) {
             return DefaultMapAdapter.adapt((Map<?, ?>) obj, this);
         }
-        if (obj instanceof Boolean) {
-            return obj.equals(Boolean.TRUE) ? TemplateBooleanModel.TRUE : 
TemplateBooleanModel.FALSE;
-        }
         if (obj instanceof Iterator) {
             return DefaultIteratorAdapter.adapt((Iterator<?>) obj, this);
         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/model/impl/SimpleCollection.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/model/impl/SimpleCollection.java 
b/src/main/java/org/apache/freemarker/core/model/impl/SimpleCollection.java
index ecae30e..cf399ab 100644
--- a/src/main/java/org/apache/freemarker/core/model/impl/SimpleCollection.java
+++ b/src/main/java/org/apache/freemarker/core/model/impl/SimpleCollection.java
@@ -52,24 +52,6 @@ implements TemplateCollectionModel, Serializable {
     private final Iterator iterator;
     private final Collection collection;
 
-    /**
-     * @deprecated Use {@link #SimpleCollection(Iterator, ObjectWrapper)}
-     */
-    @Deprecated
-    public SimpleCollection(Iterator iterator) {
-        this.iterator = iterator;
-        collection = null;
-    }
-
-    /**
-     * @deprecated Use {@link #SimpleCollection(Collection, ObjectWrapper)}
-     */
-    @Deprecated
-    public SimpleCollection(Collection collection) {
-        this.collection = collection;
-        iterator = null;
-    }
-
     public SimpleCollection(Iterator iterator, ObjectWrapper wrapper) {
         super(wrapper);
         this.iterator = iterator;
@@ -86,20 +68,16 @@ implements TemplateCollectionModel, Serializable {
      * Retrieves a template model iterator that is used to iterate over the 
elements in this collection.
      *  
      * <p>When you wrap an <tt>Iterator</tt> and you get 
<tt>TemplateModelIterator</tt> for multiple times,
-     * only on of the returned <tt>TemplateModelIterator</tt> instances can be 
really used. When you have called a
+     * only one of the returned <tt>TemplateModelIterator</tt> instances can 
be really used. When you have called a
      * method of a <tt>TemplateModelIterator</tt> instance, all other instance 
will throw a
      * <tt>TemplateModelException</tt> when you try to call their methods, 
since the wrapped <tt>Iterator</tt>
      * can't return the first element anymore.
      */
     @Override
     public TemplateModelIterator iterator() {
-        if (iterator != null) {
-            return new SimpleTemplateModelIterator(iterator, false);
-        } else {
-            synchronized (collection) {
-                return new SimpleTemplateModelIterator(collection.iterator(), 
true);
-            }
-        }
+        return iterator != null
+                ? new SimpleTemplateModelIterator(iterator, false)
+                : new SimpleTemplateModelIterator(collection.iterator(), true);
     }
     
     /**
@@ -122,7 +100,7 @@ implements TemplateCollectionModel, Serializable {
         public TemplateModel next() throws TemplateModelException {
             if (!iteratorOwnedByMe) { 
                 synchronized (SimpleCollection.this) {
-                    checkIteratorOwned();
+                    checkIteratorNotOwned();
                     iteratorOwned = true;
                     iteratorOwnedByMe = true;
                 }
@@ -141,14 +119,14 @@ implements TemplateCollectionModel, Serializable {
             // Calling hasNext may looks safe, but I have met sync. problems.
             if (!iteratorOwnedByMe) {
                 synchronized (SimpleCollection.this) {
-                    checkIteratorOwned();
+                    checkIteratorNotOwned();
                 }
             }
             
             return iterator.hasNext();
         }
         
-        private void checkIteratorOwned() throws TemplateModelException {
+        private void checkIteratorNotOwned() throws TemplateModelException {
             if (iteratorOwned) {
                 throw new TemplateModelException(
                         "This collection value wraps a java.util.Iterator, 
thus it can be listed only once.");

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/model/impl/SimpleHash.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/model/impl/SimpleHash.java 
b/src/main/java/org/apache/freemarker/core/model/impl/SimpleHash.java
index 45aa8bf..16ec685 100644
--- a/src/main/java/org/apache/freemarker/core/model/impl/SimpleHash.java
+++ b/src/main/java/org/apache/freemarker/core/model/impl/SimpleHash.java
@@ -85,34 +85,9 @@ public class SimpleHash extends WrappingTemplateModel 
implements TemplateHashMod
     private Map unwrappedMap;
 
     /**
-     * Constructs an empty hash that uses {@link 
_StaticObjectWrappers#DEFAULT_OBJECT_WRAPPER}.
-     * 
-     * @deprecated Use {@link #SimpleHash(ObjectWrapper)}
-     */
-    @Deprecated
-    public SimpleHash() {
-        this((ObjectWrapper) null);
-    }
-
-    /**
-     * Creates a new simple hash with the copy of the underlying map and the
-     * default wrapper {@link _StaticObjectWrappers#DEFAULT_OBJECT_WRAPPER}.
-     * @param map The Map to use for the key/value pairs. It makes a copy for 
-     * internal use. If the map implements the {@link SortedMap} interface, the
-     * internal copy will be a {@link TreeMap}, otherwise it will be a 
-     * {@link HashMap}.
-     * 
-     * @deprecated Use {@link #SimpleHash(Map, ObjectWrapper)}
-     */
-    @Deprecated
-    public SimpleHash(Map map) {
-        this(map, null);
-    }
-
-    /**
      * Creates an empty simple hash using the specified object wrapper.
      * @param wrapper The object wrapper to use to wrap objects into
-     * {@link TemplateModel} instances. If {@code null}, {@link 
_StaticObjectWrappers#DEFAULT_OBJECT_WRAPPER} is used.
+     * {@link TemplateModel} instances. Not {@code null}.
      */
     public SimpleHash(ObjectWrapper wrapper) {
         super(wrapper);
@@ -127,9 +102,8 @@ public class SimpleHash extends WrappingTemplateModel 
implements TemplateHashMod
      *            The Map to use for the key/value pairs. It makes a copy for 
internal use. If the map implements the
      *            {@link SortedMap} interface, the internal copy will be a 
{@link TreeMap}, otherwise it will be a
      * @param wrapper
-     *            The object wrapper to use to wrap contained objects into 
{@link TemplateModel} instances. Using
-     *            {@code null} is deprecated but allowed, in which case will 
be used
-     *            {@link _StaticObjectWrappers#DEFAULT_OBJECT_WRAPPER} is used.
+     *            The object wrapper to use to wrap contained objects into 
{@link TemplateModel} instances. Not
+     *            {@code null}.
      */
     public SimpleHash(Map map, ObjectWrapper wrapper) {
         super(wrapper);
@@ -288,39 +262,6 @@ public class SimpleHash extends WrappingTemplateModel 
implements TemplateHashMod
             put((String) entry.getKey(), entry.getValue());
         }
     }
-    
-    /**
-     * Note that this method creates and returns a deep-copy of the underlying 
hash used
-     * internally. This could be a gotcha for some people
-     * at some point who want to alter something in the data model,
-     * but we should maintain our immutability semantics (at least using 
default SimpleXXX wrappers) 
-     * for the data model. It will recursively unwrap the stuff in the 
underlying container. 
-     */
-    public Map toMap() throws TemplateModelException {
-        if (unwrappedMap == null) {
-            Class mapClass = map.getClass();
-            Map m = null;
-            try {
-                m = (Map) mapClass.newInstance();
-            } catch (Exception e) {
-                throw new TemplateModelException("Error instantiating map of 
type " + mapClass.getName() + "\n" + e.getMessage());
-            }
-            // Create a copy to maintain immutability semantics and
-            // Do nested unwrapping of elements if necessary.
-            DefaultObjectWrapper ow = 
_StaticObjectWrappers.DEFAULT_OBJECT_WRAPPER;
-            for (Iterator it = map.entrySet().iterator(); it.hasNext(); ) {
-                Map.Entry entry = (Map.Entry) it.next();
-                Object key = entry.getKey();
-                Object value = entry.getValue();
-                if (value instanceof TemplateModel) {
-                    value = ow.unwrap((TemplateModel) value);
-                }
-                m.put(key, value);
-            }
-            unwrappedMap = m;
-        }
-        return unwrappedMap;
-    }
 
     /**
      * Returns the {@code toString()} of the underlying {@link Map}.
@@ -354,75 +295,4 @@ public class SimpleHash extends WrappingTemplateModel 
implements TemplateHashMod
     public KeyValuePairIterator keyValuePairIterator() {
         return new MapKeyValuePairIterator(map, getObjectWrapper());
     }
-
-    public SimpleHash synchronizedWrapper() {
-        return new SynchronizedHash();
-    }
-    
-    private class SynchronizedHash extends SimpleHash {
-
-        @Override
-        public boolean isEmpty() {
-            synchronized (SimpleHash.this) {
-                return SimpleHash.this.isEmpty();
-            }
-        }
-        
-        @Override
-        public void put(String key, Object obj) {
-            synchronized (SimpleHash.this) {
-                SimpleHash.this.put(key, obj);
-            }
-        }
-
-        @Override
-        public TemplateModel get(String key) throws TemplateModelException {
-            synchronized (SimpleHash.this) {
-                return SimpleHash.this.get(key);
-            }
-        }
-
-        @Override
-        public void remove(String key) {
-            synchronized (SimpleHash.this) {
-                SimpleHash.this.remove(key);
-            }
-        }
-
-        @Override
-        public int size() {
-            synchronized (SimpleHash.this) {
-                return SimpleHash.this.size();
-            }
-        }
-
-        @Override
-        public TemplateCollectionModel keys() {
-            synchronized (SimpleHash.this) {
-                return SimpleHash.this.keys();
-            }
-        }
-
-        @Override
-        public TemplateCollectionModel values() {
-            synchronized (SimpleHash.this) {
-                return SimpleHash.this.values();
-            }
-        }
-
-        @Override
-        public KeyValuePairIterator keyValuePairIterator() {
-            synchronized (SimpleHash.this) {
-                return SimpleHash.this.keyValuePairIterator();
-            }
-        }
-        
-        @Override
-        public Map toMap() throws TemplateModelException {
-            synchronized (SimpleHash.this) {
-                return SimpleHash.this.toMap();
-            }
-        }
-    
-    }
 }

Reply via email to