http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/_MethodUtils.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/_MethodUtils.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/_MethodUtils.java
new file mode 100644
index 0000000..cec556f
--- /dev/null
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/_MethodUtils.java
@@ -0,0 +1,319 @@
+/*
+ * 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.model.impl;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.freemarker.core._DelayedConversionToString;
+import org.apache.freemarker.core._DelayedJQuote;
+import org.apache.freemarker.core._TemplateModelException;
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.util.BugException;
+import org.apache.freemarker.core.util._ClassUtils;
+
+/**
+ * For internal use only; don't depend on this, there's no backward 
compatibility guarantee at all!
+ */
+public final class _MethodUtils {
+    
+    private _MethodUtils() {
+        // Not meant to be instantiated
+    }
+
+    /**
+     * Determines whether the type given as the 1st argument is convertible to 
the type given as the 2nd argument
+     * for method call argument conversion. This follows the rules of the Java 
reflection-based method call, except
+     * that since we don't have the value here, a boxed class is never seen as 
convertible to a primitive type. 
+     * 
+     * @return 0 means {@code false}, non-0 means {@code true}.
+     *         That is, 0 is returned less specificity or incomparable 
specificity, also when if
+     *         then method was aborted because of {@code ifHigherThan}.
+     *         The absolute value of the returned non-0 number symbolizes how 
more specific it is:
+     *         <ul>
+     *           <li>1: The two classes are identical</li>
+     *           <li>2: The 1st type is primitive, the 2nd type is the 
corresponding boxing class</li>
+     *           <li>3: Both classes are numerical, and one is convertible 
into the other with widening conversion.
+     *                  E.g., {@code int} is convertible to {@code long} and 
{#code double}, hence {@code int} is more
+     *                  specific.
+     *                  This ignores primitive VS boxed mismatches, except 
that a boxed class is never seen as
+     *                  convertible to a primitive class.</li>
+     *           <li>4: One class is {@code instanceof} of the other, but they 
aren't identical.
+     *               But unlike in Java, primitive numerical types are {@code 
instanceof} {@link Number} here.</li>
+     *         </ul> 
+     */
+    // TODO Seems that we don't use the full functionality of this anymore, so 
we could simplify this. See usages.
+    static int isMoreOrSameSpecificParameterType(final Class<?> specific, 
final Class<?> generic, boolean bugfixed,
+            int ifHigherThan) {
+        if (ifHigherThan >= 4) return 0;
+        if (generic.isAssignableFrom(specific)) {
+            // Identity or widening reference conversion:
+            return generic == specific ? 1 : 4;
+        } else {
+            final boolean specificIsPrim = specific.isPrimitive(); 
+            final boolean genericIsPrim = generic.isPrimitive();
+            if (specificIsPrim) {
+                if (genericIsPrim) {
+                    if (ifHigherThan >= 3) return 0;
+                    return isWideningPrimitiveNumberConversion(specific, 
generic) ? 3 : 0;
+                } else {  // => specificIsPrim && !genericIsPrim
+                    if (bugfixed) {
+                        final Class<?> specificAsBoxed = 
_ClassUtils.primitiveClassToBoxingClass(specific);
+                        if (specificAsBoxed == generic) {
+                            // A primitive class is more specific than its 
boxing class, because it can't store null
+                            return 2;
+                        } else if (generic.isAssignableFrom(specificAsBoxed)) {
+                            // Note: This only occurs if `specific` is a 
primitive numerical, and `generic == Number`
+                            return 4;
+                        } else if (ifHigherThan >= 3) {
+                            return 0;
+                        } else if 
(Number.class.isAssignableFrom(specificAsBoxed)
+                                && Number.class.isAssignableFrom(generic)) {
+                            return 
isWideningBoxedNumberConversion(specificAsBoxed, generic) ? 3 : 0;
+                        } else {
+                            return 0;
+                        }
+                    } else {
+                        return 0;
+                    }
+                }
+            } else {  // => !specificIsPrim
+                if (ifHigherThan >= 3) return 0;
+                if (bugfixed && !genericIsPrim
+                        && Number.class.isAssignableFrom(specific) && 
Number.class.isAssignableFrom(generic)) {
+                    return isWideningBoxedNumberConversion(specific, generic) 
? 3 : 0;
+                } else {
+                    return 0;
+                }
+            }
+        }  // of: !generic.isAssignableFrom(specific) 
+    }
+
+    private static boolean isWideningPrimitiveNumberConversion(final Class<?> 
source, final Class<?> target) {
+        if (target == Short.TYPE && (source == Byte.TYPE)) {
+            return true;
+        } else if (target == Integer.TYPE && 
+           (source == Short.TYPE || source == Byte.TYPE)) {
+            return true;
+        } else if (target == Long.TYPE && 
+           (source == Integer.TYPE || source == Short.TYPE || 
+            source == Byte.TYPE)) {
+            return true;
+        } else if (target == Float.TYPE && 
+           (source == Long.TYPE || source == Integer.TYPE || 
+            source == Short.TYPE || source == Byte.TYPE)) {
+            return true;
+        } else if (target == Double.TYPE && 
+           (source == Float.TYPE || source == Long.TYPE || 
+            source == Integer.TYPE || source == Short.TYPE || 
+            source == Byte.TYPE)) {
+            return true; 
+        } else {
+            return false;
+        }
+    }
+
+    private static boolean isWideningBoxedNumberConversion(final Class<?> 
source, final Class<?> target) {
+        if (target == Short.class && source == Byte.class) {
+            return true;
+        } else if (target == Integer.class && 
+           (source == Short.class || source == Byte.class)) {
+            return true;
+        } else if (target == Long.class && 
+           (source == Integer.class || source == Short.class || 
+            source == Byte.class)) {
+            return true;
+        } else if (target == Float.class && 
+           (source == Long.class || source == Integer.class || 
+            source == Short.class || source == Byte.class)) {
+            return true;
+        } else if (target == Double.class && 
+           (source == Float.class || source == Long.class || 
+            source == Integer.class || source == Short.class || 
+            source == Byte.class)) {
+            return true; 
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Attention, this doesn't handle primitive classes correctly, nor 
numerical conversions.
+     */
+    static Set<Class<?>> getAssignables(Class<?> c1, Class<?> c2) {
+        Set<Class<?>> s = new HashSet<>();
+        collectAssignables(c1, c2, s);
+        return s;
+    }
+    
+    private static void collectAssignables(Class<?> c1, Class<?> c2, 
Set<Class<?>> s) {
+        if (c1.isAssignableFrom(c2)) {
+            s.add(c1);
+        }
+        Class<?> sc = c1.getSuperclass();
+        if (sc != null) {
+            collectAssignables(sc, c2, s);
+        }
+        Class<?>[] itf = c1.getInterfaces();
+        for (Class<?> anItf : itf) {
+            collectAssignables(anItf, c2, s);
+        }
+    }
+
+    public static Class<?>[] getParameterTypes(Member member) {
+        if (member instanceof Method) {
+            return ((Method) member).getParameterTypes();
+        }
+        if (member instanceof Constructor<?>) {
+            return ((Constructor<?>) member).getParameterTypes();
+        }
+        throw new IllegalArgumentException("\"member\" must be Method or 
Constructor");
+    }
+
+    static boolean isVarargs(Member member) {
+        if (member instanceof Method) { 
+            return ((Method) member).isVarArgs();
+        }
+        if (member instanceof Constructor) {
+            return ((Constructor<?>) member).isVarArgs();
+        }
+        throw new BugException();
+    }
+
+    /**
+     * Returns a more streamlined method or constructor description than 
{@code Member.toString()} does.
+     */
+    public static String toString(Member member) {
+        if (!(member instanceof Method || member instanceof Constructor)) {
+            throw new IllegalArgumentException("\"member\" must be a Method or 
Constructor");
+        }
+        
+        StringBuilder sb = new StringBuilder();
+        
+        if ((member.getModifiers() & Modifier.STATIC) != 0) {
+            sb.append("static ");
+        }
+        
+        String className = 
_ClassUtils.getShortClassName(member.getDeclaringClass());
+        if (className != null) {
+            sb.append(className);
+            sb.append('.');
+        }
+        sb.append(member.getName());
+
+        sb.append('(');
+        Class<?>[] paramTypes = _MethodUtils.getParameterTypes(member);
+        for (int i = 0; i < paramTypes.length; i++) {
+            if (i != 0) sb.append(", ");
+            String paramTypeDecl = 
_ClassUtils.getShortClassName(paramTypes[i]);
+            if (i == paramTypes.length - 1 && paramTypeDecl.endsWith("[]") && 
_MethodUtils.isVarargs(member)) {
+                sb.append(paramTypeDecl.substring(0, paramTypeDecl.length() - 
2));
+                sb.append("...");
+            } else {
+                sb.append(paramTypeDecl);
+            }
+        }
+        sb.append(')');
+        
+        return sb.toString();
+    }
+
+    static Object[] invocationErrorMessageStart(Member member) {
+        return invocationErrorMessageStart(member, member instanceof 
Constructor);
+    }
+    
+    private static Object[] invocationErrorMessageStart(Object member, boolean 
isConstructor) {
+        return new Object[] { "Java ", isConstructor ? "constructor " : 
"method ", new _DelayedJQuote(member) };
+    }
+
+    static TemplateModelException newInvocationTemplateModelException(Object 
object, Member member, Throwable e) {
+        return newInvocationTemplateModelException(
+                object,
+                member,
+                (member.getModifiers() & Modifier.STATIC) != 0,
+                member instanceof Constructor,
+                e);
+    }
+
+    static TemplateModelException newInvocationTemplateModelException(Object 
object, CallableMemberDescriptor callableMemberDescriptor, Throwable e) {
+        return newInvocationTemplateModelException(
+                object,
+                new _DelayedConversionToString(callableMemberDescriptor) {
+                    @Override
+                    protected String doConversion(Object 
callableMemberDescriptor) {
+                        return ((CallableMemberDescriptor) 
callableMemberDescriptor).getDeclaration();
+                    }
+                },
+                callableMemberDescriptor.isStatic(),
+                callableMemberDescriptor.isConstructor(),
+                e);
+    }
+    
+    private static TemplateModelException newInvocationTemplateModelException(
+            Object parentObject, Object member, boolean isStatic, boolean 
isConstructor, Throwable e) {
+        while (e instanceof InvocationTargetException) {
+            Throwable cause = ((InvocationTargetException) 
e).getTargetException();
+            if (cause != null) {
+                e = cause;
+            } else {
+                break;
+            }
+        }
+
+        return new _TemplateModelException(e,
+                invocationErrorMessageStart(member, isConstructor),
+                " threw an exception",
+                isStatic || isConstructor ? "" : new Object[] {
+                    " when invoked on ", parentObject.getClass(), " object ", 
new _DelayedJQuote(parentObject) 
+                },
+                "; see cause exception in the Java stack trace.");
+    }
+
+    /**
+     * Extracts the JavaBeans property from a reader method name, or returns 
{@code null} if the method name doesn't
+     * look like a reader method name.
+     */
+    static String getBeanPropertyNameFromReaderMethodName(String name, 
Class<?> returnType) {
+        int start;
+        if (name.startsWith("get")) {
+            start = 3;
+        } else if (returnType == boolean.class && name.startsWith("is")) {
+            start = 2;
+        } else {
+            return null;
+        }
+        int ln = name.length();
+
+        if (start == ln) {
+            return null;
+        }
+        char c1 = name.charAt(start);
+
+        return start + 1 < ln && Character.isUpperCase(name.charAt(start + 1)) 
&& Character.isUpperCase(c1)
+                ? name.substring(start) // getFOOBar => "FOOBar" (not lower 
case) according the JavaBeans spec.
+                : new StringBuilder(ln - 
start).append(Character.toLowerCase(c1)).append(name, start + 1, ln)
+                .toString();
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/_ModelAPI.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/_ModelAPI.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/_ModelAPI.java
index fecb0b0..1cb23d1 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/_ModelAPI.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/_ModelAPI.java
@@ -26,7 +26,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.freemarker.core.model.TemplateModelException;
-import org.apache.freemarker.core.util._CollectionUtil;
+import org.apache.freemarker.core.util._CollectionUtils;
 
 /**
  * For internal use only; don't depend on this, there's no backward 
compatibility guarantee at all!
@@ -50,7 +50,7 @@ public class _ModelAPI {
      */
     private static CallableMemberDescriptor getConstructorDescriptor(Class<?> 
pClass, Object[] args)
             throws NoSuchMethodException {
-        if (args == null) args = _CollectionUtil.EMPTY_OBJECT_ARRAY;
+        if (args == null) args = _CollectionUtils.EMPTY_OBJECT_ARRAY;
         
         final ArgumentTypes argTypes = new ArgumentTypes(args);
         final List<ReflectionCallableMemberDescriptor> fixedArgMemberDescs
@@ -59,7 +59,7 @@ public class _ModelAPI {
                 = new ArrayList<>();
         for (Constructor<?> constr : pClass.getConstructors()) {
             ReflectionCallableMemberDescriptor memberDesc = new 
ReflectionCallableMemberDescriptor(constr, constr.getParameterTypes());
-            if (!_MethodUtil.isVarargs(constr)) {
+            if (!_MethodUtils.isVarargs(constr)) {
                 fixedArgMemberDescs.add(memberDesc);
             } else {
                 varArgsMemberDescs.add(memberDesc);
@@ -91,7 +91,7 @@ public class _ModelAPI {
     private static Object newInstance(CallableMemberDescriptor constrDesc, 
Object[] args, DefaultObjectWrapper ow)
             throws InstantiationException, IllegalAccessException, 
InvocationTargetException, IllegalArgumentException,
             TemplateModelException {
-        if (args == null) args = _CollectionUtil.EMPTY_OBJECT_ARRAY;
+        if (args == null) args = _CollectionUtils.EMPTY_OBJECT_ARRAY;
         
         final Object[] packedArgs;
         if (constrDesc.isVarargs()) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/OutputFormat.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/OutputFormat.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/OutputFormat.java
index 9aa9e52..e354111 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/OutputFormat.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/OutputFormat.java
@@ -21,8 +21,8 @@ package org.apache.freemarker.core.outputformat;
 import org.apache.freemarker.core.Configuration;
 import org.apache.freemarker.core.model.TemplateMarkupOutputModel;
 import org.apache.freemarker.core.outputformat.impl.UndefinedOutputFormat;
-import org.apache.freemarker.core.util._ClassUtil;
-import org.apache.freemarker.core.util._StringUtil;
+import org.apache.freemarker.core.util._ClassUtils;
+import org.apache.freemarker.core.util._StringUtils;
 
 /**
  * Represents an output format. If you need auto-escaping, see its subclass, 
{@link MarkupOutputFormat}.
@@ -67,8 +67,8 @@ public abstract class OutputFormat {
     public final String toString() {
         String extras = toStringExtraProperties();
         return getName() + "("
-                + "mimeType=" + _StringUtil.jQuote(getMimeType()) + ", "
-                + "class=" + _ClassUtil.getShortClassNameOfObject(this, true)
+                + "mimeType=" + _StringUtils.jQuote(getMimeType()) + ", "
+                + "class=" + _ClassUtils.getShortClassNameOfObject(this, true)
                 + (extras.length() != 0 ? ", " : "") + extras
                 + ")";
     }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/impl/HTMLOutputFormat.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/impl/HTMLOutputFormat.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/impl/HTMLOutputFormat.java
index 0adadc0..aafcc4e 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/impl/HTMLOutputFormat.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/impl/HTMLOutputFormat.java
@@ -24,11 +24,11 @@ import java.io.Writer;
 import org.apache.freemarker.core.model.TemplateModelException;
 import org.apache.freemarker.core.outputformat.CommonMarkupOutputFormat;
 import org.apache.freemarker.core.outputformat.OutputFormat;
-import org.apache.freemarker.core.util._StringUtil;
+import org.apache.freemarker.core.util._StringUtils;
 
 /**
  * Represents the HTML output format (MIME type "text/html", name "HTML"). 
This format escapes by default (via
- * {@link _StringUtil#XHTMLEnc(String)}). The {@code ?html}, {@code ?xhtml} 
and {@code ?xml} built-ins silently bypass
+ * {@link _StringUtils#XHTMLEnc(String)}). The {@code ?html}, {@code ?xhtml} 
and {@code ?xml} built-ins silently bypass
  * template output values of the type produced by this output format ({@link 
TemplateHTMLOutputModel}).
  */
 public final class HTMLOutputFormat extends 
CommonMarkupOutputFormat<TemplateHTMLOutputModel> {
@@ -54,12 +54,12 @@ public final class HTMLOutputFormat extends 
CommonMarkupOutputFormat<TemplateHTM
 
     @Override
     public void output(String textToEsc, Writer out) throws IOException, 
TemplateModelException {
-        _StringUtil.XHTMLEnc(textToEsc, out);
+        _StringUtils.XHTMLEnc(textToEsc, out);
     }
 
     @Override
     public String escapePlainText(String plainTextContent) {
-        return _StringUtil.XHTMLEnc(plainTextContent);
+        return _StringUtils.XHTMLEnc(plainTextContent);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/impl/RTFOutputFormat.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/impl/RTFOutputFormat.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/impl/RTFOutputFormat.java
index 39a1bca..1397af5 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/impl/RTFOutputFormat.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/impl/RTFOutputFormat.java
@@ -24,11 +24,11 @@ import java.io.Writer;
 import org.apache.freemarker.core.model.TemplateModelException;
 import org.apache.freemarker.core.outputformat.CommonMarkupOutputFormat;
 import org.apache.freemarker.core.outputformat.OutputFormat;
-import org.apache.freemarker.core.util._StringUtil;
+import org.apache.freemarker.core.util._StringUtils;
 
 /**
  * Represents the Rich Text Format output format (MIME type "application/rtf", 
name "RTF"). This format escapes by
- * default (via {@link _StringUtil#RTFEnc(String)}). The {@code ?rtf} built-in 
silently bypasses template output values
+ * default (via {@link _StringUtils#RTFEnc(String)}). The {@code ?rtf} 
built-in silently bypasses template output values
  * of the type produced by this output format ({@link TemplateRTFOutputModel}).
  */
 public final class RTFOutputFormat extends 
CommonMarkupOutputFormat<TemplateRTFOutputModel> {
@@ -54,12 +54,12 @@ public final class RTFOutputFormat extends 
CommonMarkupOutputFormat<TemplateRTFO
 
     @Override
     public void output(String textToEsc, Writer out) throws IOException, 
TemplateModelException {
-        _StringUtil.RTFEnc(textToEsc, out);
+        _StringUtils.RTFEnc(textToEsc, out);
     }
 
     @Override
     public String escapePlainText(String plainTextContent) {
-        return _StringUtil.RTFEnc(plainTextContent);
+        return _StringUtils.RTFEnc(plainTextContent);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/impl/XHTMLOutputFormat.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/impl/XHTMLOutputFormat.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/impl/XHTMLOutputFormat.java
index 769b33f..55a2748 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/impl/XHTMLOutputFormat.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/impl/XHTMLOutputFormat.java
@@ -24,11 +24,11 @@ import java.io.Writer;
 import org.apache.freemarker.core.model.TemplateModelException;
 import org.apache.freemarker.core.outputformat.CommonMarkupOutputFormat;
 import org.apache.freemarker.core.outputformat.OutputFormat;
-import org.apache.freemarker.core.util._StringUtil;
+import org.apache.freemarker.core.util._StringUtils;
 
 /**
  * Represents the XML output format (MIME type "application/xhtml+xml", name 
"XHTML"). This format escapes by default
- * (via {@link _StringUtil#XHTMLEnc(String)}). The {@code ?xml} built-in 
silently bypasses template output values of the
+ * (via {@link _StringUtils#XHTMLEnc(String)}). The {@code ?xml} built-in 
silently bypasses template output values of the
  * type produced by this output format ({@link TemplateXHTMLOutputModel}).
  */
 public final class XHTMLOutputFormat extends 
CommonMarkupOutputFormat<TemplateXHTMLOutputModel> {
@@ -54,12 +54,12 @@ public final class XHTMLOutputFormat extends 
CommonMarkupOutputFormat<TemplateXH
 
     @Override
     public void output(String textToEsc, Writer out) throws IOException, 
TemplateModelException {
-        _StringUtil.XHTMLEnc(textToEsc, out);
+        _StringUtils.XHTMLEnc(textToEsc, out);
     }
 
     @Override
     public String escapePlainText(String plainTextContent) {
-        return _StringUtil.XHTMLEnc(plainTextContent);
+        return _StringUtils.XHTMLEnc(plainTextContent);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/impl/XMLOutputFormat.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/impl/XMLOutputFormat.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/impl/XMLOutputFormat.java
index 4b03d31..c129135 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/impl/XMLOutputFormat.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/outputformat/impl/XMLOutputFormat.java
@@ -24,11 +24,11 @@ import java.io.Writer;
 import org.apache.freemarker.core.model.TemplateModelException;
 import org.apache.freemarker.core.outputformat.CommonMarkupOutputFormat;
 import org.apache.freemarker.core.outputformat.OutputFormat;
-import org.apache.freemarker.core.util._StringUtil;
+import org.apache.freemarker.core.util._StringUtils;
 
 /**
  * Represents the XML output format (MIME type "application/xml", name "XML"). 
This format escapes by default (via
- * {@link _StringUtil#XMLEnc(String)}). The {@code ?html}, {@code ?xhtml} and 
{@code ?xml} built-ins silently bypass
+ * {@link _StringUtils#XMLEnc(String)}). The {@code ?html}, {@code ?xhtml} and 
{@code ?xml} built-ins silently bypass
  * template output values of the type produced by this output format ({@link 
TemplateXHTMLOutputModel}).
  */
 public final class XMLOutputFormat extends 
CommonMarkupOutputFormat<TemplateXMLOutputModel> {
@@ -54,12 +54,12 @@ public final class XMLOutputFormat extends 
CommonMarkupOutputFormat<TemplateXMLO
 
     @Override
     public void output(String textToEsc, Writer out) throws IOException, 
TemplateModelException {
-        _StringUtil.XMLEnc(textToEsc, out);
+        _StringUtils.XMLEnc(textToEsc, out);
     }
 
     @Override
     public String escapePlainText(String plainTextContent) {
-        return _StringUtil.XMLEnc(plainTextContent);
+        return _StringUtils.XMLEnc(plainTextContent);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/FileNameGlobMatcher.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/FileNameGlobMatcher.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/FileNameGlobMatcher.java
index 3db052d..443b9e6 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/FileNameGlobMatcher.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/FileNameGlobMatcher.java
@@ -21,7 +21,7 @@ package org.apache.freemarker.core.templateresolver;
 import java.io.IOException;
 import java.util.regex.Pattern;
 
-import org.apache.freemarker.core.util._StringUtil;
+import org.apache.freemarker.core.util._StringUtils;
 
 /**
  * As opposed to {@link PathGlobMatcher}, it only compares the "file name" 
part (the part after the last {@code /}) of
@@ -38,7 +38,7 @@ public class FileNameGlobMatcher extends 
TemplateSourceMatcher {
     
     /**
      * @param glob
-     *            Glob with the syntax defined by {@link 
_StringUtil#globToRegularExpression(String, boolean)}. Must not
+     *            Glob with the syntax defined by {@link 
_StringUtils#globToRegularExpression(String, boolean)}. Must not
      *            start with {@code /}.
      */
     public FileNameGlobMatcher(String glob) {
@@ -50,7 +50,7 @@ public class FileNameGlobMatcher extends 
TemplateSourceMatcher {
     }
 
     private void buildPattern() {
-        pattern = _StringUtil.globToRegularExpression("**/" + glob, 
caseInsensitive);
+        pattern = _StringUtils.globToRegularExpression("**/" + glob, 
caseInsensitive);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/FirstMatchTemplateConfigurationFactory.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/FirstMatchTemplateConfigurationFactory.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/FirstMatchTemplateConfigurationFactory.java
index 0f09d3d..97218e3 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/FirstMatchTemplateConfigurationFactory.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/FirstMatchTemplateConfigurationFactory.java
@@ -21,7 +21,7 @@ package org.apache.freemarker.core.templateresolver;
 import java.io.IOException;
 
 import org.apache.freemarker.core.TemplateConfiguration;
-import org.apache.freemarker.core.util._StringUtil;
+import org.apache.freemarker.core.util._StringUtils;
 
 /**
  * Returns the first non-{@code null} result of the child factories, ignoring 
all further child factories. The child
@@ -50,7 +50,7 @@ public class FirstMatchTemplateConfigurationFactory extends 
TemplateConfiguratio
             throw new TemplateConfigurationFactoryException(
                     
FirstMatchTemplateConfigurationFactory.class.getSimpleName()
                     + " has found no matching choice for source name "
-                    + _StringUtil.jQuote(sourceName) + ". "
+                    + _StringUtils.jQuote(sourceName) + ". "
                     + (noMatchErrorDetails != null
                             ? "Error details: " + noMatchErrorDetails 
                             : "(Set the noMatchErrorDetails property of the 
factory bean to give a more specific error "

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/MalformedTemplateNameException.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/MalformedTemplateNameException.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/MalformedTemplateNameException.java
index 49c3b88..0c675cd 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/MalformedTemplateNameException.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/MalformedTemplateNameException.java
@@ -23,7 +23,7 @@ import java.io.IOException;
 
 import org.apache.freemarker.core.Configuration;
 import org.apache.freemarker.core.TemplateNotFoundException;
-import org.apache.freemarker.core.util._StringUtil;
+import org.apache.freemarker.core.util._StringUtils;
 
 /**
  * Indicates that the template name given was malformed according the {@link 
TemplateNameFormat} in use.
@@ -40,7 +40,7 @@ public class MalformedTemplateNameException extends 
IOException {
     private final String malformednessDescription;
 
     public MalformedTemplateNameException(String templateName, String 
malformednessDescription) {
-        super("Malformed template name, " + _StringUtil.jQuote(templateName) + 
": " + malformednessDescription);
+        super("Malformed template name, " + _StringUtils.jQuote(templateName) 
+ ": " + malformednessDescription);
         this.templateName = templateName;
         this.malformednessDescription = malformednessDescription;
     }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/PathGlobMatcher.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/PathGlobMatcher.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/PathGlobMatcher.java
index 17d1b94..34164d2 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/PathGlobMatcher.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/PathGlobMatcher.java
@@ -21,7 +21,7 @@ package org.apache.freemarker.core.templateresolver;
 import java.io.IOException;
 import java.util.regex.Pattern;
 
-import org.apache.freemarker.core.util._StringUtil;
+import org.apache.freemarker.core.util._StringUtils;
 
 /**
  * Matches the whole template source name (also known as template source path) 
with the given glob.
@@ -29,7 +29,7 @@ import org.apache.freemarker.core.util._StringUtil;
  * it's not the full path of a file on the file system.
  * 
  * <p>This glob implementation recognizes {@code **} (Ant-style directory 
wildcard) among others. For more details see
- * {@link _StringUtil#globToRegularExpression(String, boolean)}.
+ * {@link _StringUtils#globToRegularExpression(String, boolean)}.
  * 
  * <p>About the usage of {@code /} (slash):
  * <ul>
@@ -52,7 +52,7 @@ public class PathGlobMatcher extends TemplateSourceMatcher {
     
     /**
      * @param glob
-     *            Glob with the syntax defined by {@link 
_StringUtil#globToRegularExpression(String, boolean)}. Must not
+     *            Glob with the syntax defined by {@link 
_StringUtils#globToRegularExpression(String, boolean)}. Must not
      *            start with {@code /}.
      */
     public PathGlobMatcher(String glob) {
@@ -64,7 +64,7 @@ public class PathGlobMatcher extends TemplateSourceMatcher {
     }
 
     private void buildPattern() {
-        pattern = _StringUtil.globToRegularExpression(glob, caseInsensitive);
+        pattern = _StringUtils.globToRegularExpression(glob, caseInsensitive);
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/PathRegexMatcher.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/PathRegexMatcher.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/PathRegexMatcher.java
index 347408b..e568e1a 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/PathRegexMatcher.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/PathRegexMatcher.java
@@ -21,7 +21,7 @@ package org.apache.freemarker.core.templateresolver;
 import java.io.IOException;
 import java.util.regex.Pattern;
 
-import org.apache.freemarker.core.util._StringUtil;
+import org.apache.freemarker.core.util._StringUtils;
 
 /**
  * Matches the whole template source name (also known as template source path) 
with the given regular expression.
@@ -34,7 +34,7 @@ public class PathRegexMatcher extends TemplateSourceMatcher {
     
     /**
      * @param regex
-     *            Glob with the syntax defined by {@link 
_StringUtil#globToRegularExpression(String)}. Must not
+     *            Glob with the syntax defined by {@link 
_StringUtils#globToRegularExpression(String)}. Must not
      *            start with {@code /}.
      */
     public PathRegexMatcher(String regex) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/ByteArrayTemplateLoader.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/ByteArrayTemplateLoader.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/ByteArrayTemplateLoader.java
index 8df63ed..28a8671 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/ByteArrayTemplateLoader.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/ByteArrayTemplateLoader.java
@@ -34,7 +34,7 @@ import 
org.apache.freemarker.core.templateresolver.TemplateLoader;
 import org.apache.freemarker.core.templateresolver.TemplateLoaderSession;
 import org.apache.freemarker.core.templateresolver.TemplateLoadingResult;
 import org.apache.freemarker.core.templateresolver.TemplateLoadingSource;
-import org.apache.freemarker.core.util._StringUtil;
+import org.apache.freemarker.core.util._StringUtils;
 
 /**
  * A {@link TemplateLoader} that uses a {@link Map} with {@code byte[]} as its 
source of templates. This is similar to
@@ -132,7 +132,7 @@ public class ByteArrayTemplateLoader implements 
TemplateLoader {
                 sb.append("...");
                 break;
             }
-            sb.append(_StringUtil.jQuote(name));
+            sb.append(_StringUtils.jQuote(name));
             sb.append("=...");
         }
         if (cnt != 0) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/ClassTemplateLoader.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/ClassTemplateLoader.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/ClassTemplateLoader.java
index 331307f..414d137 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/ClassTemplateLoader.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/ClassTemplateLoader.java
@@ -26,7 +26,7 @@ import java.net.URLConnection;
 import org.apache.freemarker.core.templateresolver.TemplateLoader;
 import org.apache.freemarker.core.templateresolver.TemplateLoadingResult;
 import org.apache.freemarker.core.util._NullArgumentException;
-import org.apache.freemarker.core.util._StringUtil;
+import org.apache.freemarker.core.util._StringUtils;
 
 /**
  * A {@link TemplateLoader} that can load templates from the "classpath". 
Naturally, it can load from jar files, or from
@@ -128,10 +128,10 @@ public class ClassTemplateLoader extends 
URLTemplateLoader {
         return _TemplateLoaderUtils.getClassNameForToString(this) + "("
                 + (resourceLoaderClass != null
                         ? "resourceLoaderClass=" + 
resourceLoaderClass.getName()
-                        : "classLoader=" + _StringUtil.jQuote(classLoader))
+                        : "classLoader=" + _StringUtils.jQuote(classLoader))
                 + ", basePackagePath"
                 + "="
-                + _StringUtil.jQuote(basePackagePath)
+                + _StringUtils.jQuote(basePackagePath)
                 + (resourceLoaderClass != null
                         ? (basePackagePath.startsWith("/") ? "" : " /* 
relatively to resourceLoaderClass pkg */")
                         : ""

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateNameFormat.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateNameFormat.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateNameFormat.java
index 4144e34..ff2049d 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateNameFormat.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateNameFormat.java
@@ -25,7 +25,7 @@ import org.apache.freemarker.core.Configuration;
 import 
org.apache.freemarker.core.templateresolver.MalformedTemplateNameException;
 import org.apache.freemarker.core.templateresolver.TemplateLoader;
 import org.apache.freemarker.core.templateresolver.TemplateNameFormat;
-import org.apache.freemarker.core.util._StringUtil;
+import org.apache.freemarker.core.util._StringUtils;
 
 /**
  * The default {@linkplain Configuration#getTemplateNameFormat()} template 
name format}. This defines a format where
@@ -151,7 +151,7 @@ public final class DefaultTemplateNameFormat extends 
TemplateNameFormat {
         String prevName;
         do {
             prevName = path;
-            path = _StringUtil.replace(path, "//", "/");
+            path = _StringUtils.replace(path, "//", "/");
         } while (prevName != path);
         return path.startsWith("/") ? path.substring(1) : path;
     }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateResolver.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateResolver.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateResolver.java
index 2504ccc..aaf09bc 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateResolver.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateResolver.java
@@ -59,7 +59,7 @@ import 
org.apache.freemarker.core.templateresolver.TemplateResolverDependencies;
 import org.apache.freemarker.core.util.BugException;
 import org.apache.freemarker.core.util.UndeclaredThrowableException;
 import org.apache.freemarker.core.util._NullArgumentException;
-import org.apache.freemarker.core.util._StringUtil;
+import org.apache.freemarker.core.util._StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -309,8 +309,8 @@ public class DefaultTemplateResolver extends 
TemplateResolver {
                             Object newSource = 
newTemplateLoaderResult.getSource();
                             if (!nullSafeEquals(newSource, 
oldCachedResult.source)) {
                                 debugMsg.append("the source has been changed: 
")
-                                        
.append("cached.source=").append(_StringUtil.jQuoteNoXSS(oldCachedResult.source))
-                                        .append(", 
current.source=").append(_StringUtil.jQuoteNoXSS(newSource));
+                                        
.append("cached.source=").append(_StringUtils.jQuoteNoXSS(oldCachedResult.source))
+                                        .append(", 
current.source=").append(_StringUtils.jQuoteNoXSS(newSource));
                             } else {
                                 Serializable newVersion = 
newTemplateLoaderResult.getVersion();
                                 if (!nullSafeEquals(oldCachedResult.version, 
newVersion)) {
@@ -354,7 +354,7 @@ public class DefaultTemplateResolver extends 
TemplateResolver {
             // If we get here, then we need to (re)load the template
             if (debug) {
                 LOG.debug(debugPrefix + "Reading template content (source: "
-                        + _StringUtil.jQuoteNoXSS(newCachedResult.source) + 
")");
+                        + _StringUtils.jQuoteNoXSS(newCachedResult.source) + 
")");
             }
             
             Template template = loadTemplate(
@@ -576,7 +576,7 @@ public class DefaultTemplateResolver extends 
TemplateResolver {
                         reader = new InputStreamReader(inputStream, 
templateSpecifiedEncoding);
                     } else {
                         throw new IllegalStateException(
-                                "TemplateLanguage " + 
_StringUtil.jQuote(templateLanguage.getName()) + " has thrown "
+                                "TemplateLanguage " + 
_StringUtils.jQuote(templateLanguage.getName()) + " has thrown "
                                 + WrongTemplateCharsetException.class.getName()
                                 + ", but its canSpecifyCharsetInContent 
property is false.");
                     }
@@ -650,9 +650,9 @@ public class DefaultTemplateResolver extends 
TemplateResolver {
     }
 
     private String getDebugPrefix(String operation, String name, Locale 
locale, Object customLookupCondition) {
-        return operation + " " + _StringUtil.jQuoteNoXSS(name) + "("
-                + _StringUtil.jQuoteNoXSS(locale)
-                + (customLookupCondition != null ? ", cond=" + 
_StringUtil.jQuoteNoXSS(customLookupCondition) : "")
+        return operation + " " + _StringUtils.jQuoteNoXSS(name) + "("
+                + _StringUtils.jQuoteNoXSS(locale)
+                + (customLookupCondition != null ? ", cond=" + 
_StringUtils.jQuoteNoXSS(customLookupCondition) : "")
                 + "): ";
     }    
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/FileTemplateLoader.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/FileTemplateLoader.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/FileTemplateLoader.java
index 4976746..e738351 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/FileTemplateLoader.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/FileTemplateLoader.java
@@ -36,8 +36,8 @@ import 
org.apache.freemarker.core.templateresolver.TemplateLoader;
 import org.apache.freemarker.core.templateresolver.TemplateLoaderSession;
 import org.apache.freemarker.core.templateresolver.TemplateLoadingResult;
 import org.apache.freemarker.core.templateresolver.TemplateLoadingSource;
-import org.apache.freemarker.core.util._SecurityUtil;
-import org.apache.freemarker.core.util._StringUtil;
+import org.apache.freemarker.core.util._SecurityUtils;
+import org.apache.freemarker.core.util._StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -58,11 +58,11 @@ public class FileTemplateLoader implements TemplateLoader {
             = "org.freemarker.emulateCaseSensitiveFileSystem";
     private static final boolean EMULATE_CASE_SENSITIVE_FILE_SYSTEM_DEFAULT;
     static {
-        final String s = 
_SecurityUtil.getSystemProperty(SYSTEM_PROPERTY_NAME_EMULATE_CASE_SENSITIVE_FILE_SYSTEM,
+        final String s = 
_SecurityUtils.getSystemProperty(SYSTEM_PROPERTY_NAME_EMULATE_CASE_SENSITIVE_FILE_SYSTEM,
                 "false");
         boolean emuCaseSensFS;
         try {
-            emuCaseSensFS = _StringUtil.getYesNo(s);
+            emuCaseSensFS = _StringUtils.getYesNo(s);
         } catch (Exception e) {
             emuCaseSensFS = false;
         }
@@ -306,7 +306,7 @@ public class FileTemplateLoader implements TemplateLoader {
      */
     @Override
     public String toString() {
-        // We don't _StringUtil.jQuote paths here, because on Windows there 
will be \\-s then that some may find
+        // We don't _StringUtils.jQuote paths here, because on Windows there 
will be \\-s then that some may find
         // confusing.
         return _TemplateLoaderUtils.getClassNameForToString(this) + "("
                 + "baseDir=\"" + baseDir + "\""

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/StringTemplateLoader.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/StringTemplateLoader.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/StringTemplateLoader.java
index 7cc52ac..47e3b7a 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/StringTemplateLoader.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/StringTemplateLoader.java
@@ -34,7 +34,7 @@ import 
org.apache.freemarker.core.templateresolver.TemplateLoader;
 import org.apache.freemarker.core.templateresolver.TemplateLoaderSession;
 import org.apache.freemarker.core.templateresolver.TemplateLoadingResult;
 import org.apache.freemarker.core.templateresolver.TemplateLoadingSource;
-import org.apache.freemarker.core.util._StringUtil;
+import org.apache.freemarker.core.util._StringUtils;
 
 /**
  * A {@link TemplateLoader} that uses a {@link Map} with {@code String} as its 
source of templates. This is similar to
@@ -132,7 +132,7 @@ public class StringTemplateLoader implements TemplateLoader 
{
                 sb.append("...");
                 break;
             }
-            sb.append(_StringUtil.jQuote(name));
+            sb.append(_StringUtils.jQuote(name));
             sb.append("=...");
         }
         if (cnt != 0) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/util/DuplicateStringKeyException.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/util/DuplicateStringKeyException.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/util/DuplicateStringKeyException.java
index a598694..2456dda 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/util/DuplicateStringKeyException.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/util/DuplicateStringKeyException.java
@@ -28,7 +28,7 @@ public class DuplicateStringKeyException extends 
IllegalArgumentException {
     private final String key;
 
     public DuplicateStringKeyException(String key) {
-        super("Duplicate key: " + _StringUtil.jQuote(key));
+        super("Duplicate key: " + _StringUtils.jQuote(key));
         this.key = key;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/util/FTLUtil.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/util/FTLUtil.java 
b/freemarker-core/src/main/java/org/apache/freemarker/core/util/FTLUtil.java
index 7c58284..1b5e04a 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/util/FTLUtil.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/util/FTLUtil.java
@@ -721,13 +721,13 @@ public final class FTLUtil {
             String javaClassName;
             Class unwrappedClass = getUnwrappedClass(tm);
             if (unwrappedClass != null) {
-                javaClassName = _ClassUtil.getShortClassName(unwrappedClass, 
true);
+                javaClassName = _ClassUtils.getShortClassName(unwrappedClass, 
true);
             } else {
                 javaClassName = null;
             }
 
             sb.append(" (");
-            String modelClassName = 
_ClassUtil.getShortClassName(tm.getClass(), true);
+            String modelClassName = 
_ClassUtils.getShortClassName(tm.getClass(), true);
             if (javaClassName == null) {
                 sb.append("wrapper: ");
                 sb.append(modelClassName);

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/util/OptInTemplateClassResolver.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/util/OptInTemplateClassResolver.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/util/OptInTemplateClassResolver.java
index faf8e73..558e09d 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/util/OptInTemplateClassResolver.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/util/OptInTemplateClassResolver.java
@@ -108,7 +108,7 @@ public class OptInTemplateClassResolver implements 
TemplateClassResolver {
                         "\" setting in the FreeMarker configuration.)");
             } else {
                 try {
-                    return _ClassUtil.forName(className);
+                    return _ClassUtils.forName(className);
                 } catch (ClassNotFoundException e) {
                     throw new _MiscTemplateException(e, env);
                 }
@@ -129,12 +129,12 @@ public class OptInTemplateClassResolver implements 
TemplateClassResolver {
         // Detect exploits, return null if one is suspected:
         String decodedName = name;
         if (decodedName.indexOf('%') != -1) {
-            decodedName = _StringUtil.replace(decodedName, "%2e", ".", false, 
false);
-            decodedName = _StringUtil.replace(decodedName, "%2E", ".", false, 
false);
-            decodedName = _StringUtil.replace(decodedName, "%2f", "/", false, 
false);
-            decodedName = _StringUtil.replace(decodedName, "%2F", "/", false, 
false);
-            decodedName = _StringUtil.replace(decodedName, "%5c", "\\", false, 
false);
-            decodedName = _StringUtil.replace(decodedName, "%5C", "\\", false, 
false);
+            decodedName = _StringUtils.replace(decodedName, "%2e", ".", false, 
false);
+            decodedName = _StringUtils.replace(decodedName, "%2E", ".", false, 
false);
+            decodedName = _StringUtils.replace(decodedName, "%2f", "/", false, 
false);
+            decodedName = _StringUtils.replace(decodedName, "%2F", "/", false, 
false);
+            decodedName = _StringUtils.replace(decodedName, "%5c", "\\", 
false, false);
+            decodedName = _StringUtils.replace(decodedName, "%5C", "\\", 
false, false);
         }
         int dotDotIdx = decodedName.indexOf("..");
         if (dotDotIdx != -1) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/util/StringToIndexMap.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/util/StringToIndexMap.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/util/StringToIndexMap.java
index 65e8153..feb9586 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/util/StringToIndexMap.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/util/StringToIndexMap.java
@@ -262,7 +262,7 @@ public final class StringToIndexMap {
             while (entry != null) {
                 if (entry.value < start || entry.value >= end) {
                     throw new IllegalArgumentException(
-                            "Entry " + _StringUtil.jQuote(entry.key) + " -> " 
+ entry.value
+                            "Entry " + _StringUtils.jQuote(entry.key) + " -> " 
+ entry.value
                             + " is out of allowed index range: " + start + " 
..< " + end);
                 }
                 entry = entry.nextInSameBucket;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/util/UnrecognizedTimeZoneException.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/util/UnrecognizedTimeZoneException.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/util/UnrecognizedTimeZoneException.java
index 4a820a0..7894257 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/util/UnrecognizedTimeZoneException.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/util/UnrecognizedTimeZoneException.java
@@ -27,7 +27,7 @@ public class UnrecognizedTimeZoneException extends Exception {
     private final String timeZoneName;
 
     public UnrecognizedTimeZoneException(String timeZoneName) {
-        super("Unrecognized time zone: " + _StringUtil.jQuote(timeZoneName));
+        super("Unrecognized time zone: " + _StringUtils.jQuote(timeZoneName));
         this.timeZoneName = timeZoneName;
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/util/_ClassUtil.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_ClassUtil.java 
b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_ClassUtil.java
deleted file mode 100644
index 7a605b1..0000000
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_ClassUtil.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.freemarker.core.util;
-
-import org.apache.freemarker.core.model.impl.BeanModel;
-
-public class _ClassUtil {
-    
-    private static final String ORG_APACHE_FREEMARKER = 
"org.apache.freemarker.";
-    private static final String ORG_APACHE_FREEMARKER_CORE = 
"org.apache.freemarker.core.";
-    private static final String ORG_APACHE_FREEMARKER_CORE_TEMPLATERESOLVER
-            = "org.apache.freemarker.core.templateresolver.";
-    private static final String ORG_APACHE_FREEMARKER_CORE_MODEL = 
"org.apache.freemarker.core.model.";
-
-    private _ClassUtil() {
-    }
-    
-    /**
-     * Similar to {@link Class#forName(java.lang.String)}, but attempts to load
-     * through the thread context class loader. Only if thread context class
-     * loader is inaccessible, or it can't find the class will it attempt to
-     * fall back to the class loader that loads the FreeMarker classes.
-     */
-    public static Class forName(String className)
-    throws ClassNotFoundException {
-        try {
-            ClassLoader ctcl = Thread.currentThread().getContextClassLoader();
-            if (ctcl != null) {  // not null: we don't want to fall back to 
the bootstrap class loader
-                return Class.forName(className, true, ctcl);
-            }
-        } catch (ClassNotFoundException e) {
-            // Intentionally ignored
-        } catch (SecurityException e) {
-            // Intentionally ignored
-        }
-        // Fall back to the defining class loader of the FreeMarker classes 
-        return Class.forName(className);
-    }
-    
-    /**
-     * Same as {@link #getShortClassName(Class, boolean) 
getShortClassName(pClass, false)}.
-     */
-    public static String getShortClassName(Class pClass) {
-        return getShortClassName(pClass, false);
-    }
-    
-    /**
-     * Returns a class name without "java.lang." and "java.util." prefix, also 
shows array types in a format like
-     * {@code int[]}; useful for printing class names in error messages.
-     * 
-     * @param pClass can be {@code null}, in which case the method returns 
{@code null}.
-     * @param shortenFreeMarkerClasses if {@code true}, it will also shorten 
FreeMarker class names. The exact rules
-     *     aren't specified and might change over time, but right now, {@link 
BeanModel} for
-     *     example becomes to {@code o.a.f.c.m.BeanModel}.
-     */
-    public static String getShortClassName(Class pClass, boolean 
shortenFreeMarkerClasses) {
-        if (pClass == null) {
-            return null;
-        } else if (pClass.isArray()) {
-            return getShortClassName(pClass.getComponentType()) + "[]";
-        } else {
-            String cn = pClass.getName();
-            if (cn.startsWith("java.lang.") || cn.startsWith("java.util.")) {
-                return cn.substring(10);
-            } else {
-                if (shortenFreeMarkerClasses) {
-                    if (cn.startsWith(ORG_APACHE_FREEMARKER_CORE_MODEL)) {
-                        return "o.a.f.c.m." + 
cn.substring(ORG_APACHE_FREEMARKER_CORE_MODEL.length());
-                    } else if 
(cn.startsWith(ORG_APACHE_FREEMARKER_CORE_TEMPLATERESOLVER)) {
-                        return "o.a.f.c.t." + 
cn.substring(ORG_APACHE_FREEMARKER_CORE_TEMPLATERESOLVER.length());
-                    } else if (cn.startsWith(ORG_APACHE_FREEMARKER_CORE)) {
-                        return "o.a.f.c." + 
cn.substring(ORG_APACHE_FREEMARKER_CORE.length());
-                    } else if (cn.startsWith(ORG_APACHE_FREEMARKER)) {
-                        return "o.a.f." + 
cn.substring(ORG_APACHE_FREEMARKER.length());
-                    }
-                    // Falls through
-                }
-                return cn;
-            }
-        }
-    }
-
-    /**
-     * Same as {@link #getShortClassNameOfObject(Object, boolean) 
getShortClassNameOfObject(pClass, false)}.
-     */
-    public static String getShortClassNameOfObject(Object obj) {
-        return getShortClassNameOfObject(obj, false);
-    }
-    
-    /**
-     * {@link #getShortClassName(Class, boolean)} called with {@code 
object.getClass()}, but returns the fictional
-     * class name {@code Null} for a {@code null} value.
-     */
-    public static String getShortClassNameOfObject(Object obj, boolean 
shortenFreeMarkerClasses) {
-        if (obj == null) {
-            return "Null";
-        } else {
-            return _ClassUtil.getShortClassName(obj.getClass(), 
shortenFreeMarkerClasses);
-        }
-    }
-
-    /**
-     * Gets the wrapper class for a primitive class, like {@link Integer} for 
{@code int}, also returns {@link Void}
-     * for {@code void}. 
-     * 
-     * @param primitiveClass A {@link Class} like {@code int.type}, {@code 
boolean.type}, etc. If it's not a primitive
-     *     class, or it's {@code null}, then the parameter value is returned 
as is. Note that performance-wise the
-     *     method assumes that it's a primitive class.
-     */
-    public static Class primitiveClassToBoxingClass(Class primitiveClass) {
-        // Tried to sort these with decreasing frequency in API-s:
-        if (primitiveClass == int.class) return Integer.class;
-        if (primitiveClass == boolean.class) return Boolean.class;
-        if (primitiveClass == long.class) return Long.class;
-        if (primitiveClass == double.class) return Double.class;
-        if (primitiveClass == char.class) return Character.class;
-        if (primitiveClass == float.class) return Float.class;
-        if (primitiveClass == byte.class) return Byte.class;
-        if (primitiveClass == short.class) return Short.class;
-        if (primitiveClass == void.class) return Void.class;  // not really a 
primitive, but we normalize it
-        return primitiveClass;
-    }
-
-    /**
-     * The exact reverse of {@link #primitiveClassToBoxingClass}.
-     */
-    public static Class boxingClassToPrimitiveClass(Class boxingClass) {
-        // Tried to sort these with decreasing frequency in API-s:
-        if (boxingClass == Integer.class) return int.class;
-        if (boxingClass == Boolean.class) return boolean.class;
-        if (boxingClass == Long.class) return long.class;
-        if (boxingClass == Double.class) return double.class;
-        if (boxingClass == Character.class) return char.class;
-        if (boxingClass == Float.class) return float.class;
-        if (boxingClass == Byte.class) return byte.class;
-        if (boxingClass == Short.class) return short.class;
-        if (boxingClass == Void.class) return void.class;  // not really a 
primitive, but we normalize to it
-        return boxingClass;
-    }
-    
-    /**
-     * Tells if a type is numerical; works both for primitive types and 
classes.
-     * 
-     * @param type can't be {@code null}
-     */
-    public static boolean isNumerical(Class type) {
-        return Number.class.isAssignableFrom(type)
-                || type.isPrimitive() && type != Boolean.TYPE && type != 
Character.TYPE && type != Void.TYPE;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/util/_ClassUtils.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_ClassUtils.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_ClassUtils.java
new file mode 100644
index 0000000..d229c2d
--- /dev/null
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_ClassUtils.java
@@ -0,0 +1,168 @@
+/*
+ * 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.util;
+
+import org.apache.freemarker.core.model.impl.BeanModel;
+
+public class _ClassUtils {
+    
+    private static final String ORG_APACHE_FREEMARKER = 
"org.apache.freemarker.";
+    private static final String ORG_APACHE_FREEMARKER_CORE = 
"org.apache.freemarker.core.";
+    private static final String ORG_APACHE_FREEMARKER_CORE_TEMPLATERESOLVER
+            = "org.apache.freemarker.core.templateresolver.";
+    private static final String ORG_APACHE_FREEMARKER_CORE_MODEL = 
"org.apache.freemarker.core.model.";
+
+    private _ClassUtils() {
+    }
+    
+    /**
+     * Similar to {@link Class#forName(java.lang.String)}, but attempts to load
+     * through the thread context class loader. Only if thread context class
+     * loader is inaccessible, or it can't find the class will it attempt to
+     * fall back to the class loader that loads the FreeMarker classes.
+     */
+    public static Class forName(String className)
+    throws ClassNotFoundException {
+        try {
+            ClassLoader ctcl = Thread.currentThread().getContextClassLoader();
+            if (ctcl != null) {  // not null: we don't want to fall back to 
the bootstrap class loader
+                return Class.forName(className, true, ctcl);
+            }
+        } catch (ClassNotFoundException e) {
+            // Intentionally ignored
+        } catch (SecurityException e) {
+            // Intentionally ignored
+        }
+        // Fall back to the defining class loader of the FreeMarker classes 
+        return Class.forName(className);
+    }
+    
+    /**
+     * Same as {@link #getShortClassName(Class, boolean) 
getShortClassName(pClass, false)}.
+     */
+    public static String getShortClassName(Class pClass) {
+        return getShortClassName(pClass, false);
+    }
+    
+    /**
+     * Returns a class name without "java.lang." and "java.util." prefix, also 
shows array types in a format like
+     * {@code int[]}; useful for printing class names in error messages.
+     * 
+     * @param pClass can be {@code null}, in which case the method returns 
{@code null}.
+     * @param shortenFreeMarkerClasses if {@code true}, it will also shorten 
FreeMarker class names. The exact rules
+     *     aren't specified and might change over time, but right now, {@link 
BeanModel} for
+     *     example becomes to {@code o.a.f.c.m.BeanModel}.
+     */
+    public static String getShortClassName(Class pClass, boolean 
shortenFreeMarkerClasses) {
+        if (pClass == null) {
+            return null;
+        } else if (pClass.isArray()) {
+            return getShortClassName(pClass.getComponentType()) + "[]";
+        } else {
+            String cn = pClass.getName();
+            if (cn.startsWith("java.lang.") || cn.startsWith("java.util.")) {
+                return cn.substring(10);
+            } else {
+                if (shortenFreeMarkerClasses) {
+                    if (cn.startsWith(ORG_APACHE_FREEMARKER_CORE_MODEL)) {
+                        return "o.a.f.c.m." + 
cn.substring(ORG_APACHE_FREEMARKER_CORE_MODEL.length());
+                    } else if 
(cn.startsWith(ORG_APACHE_FREEMARKER_CORE_TEMPLATERESOLVER)) {
+                        return "o.a.f.c.t." + 
cn.substring(ORG_APACHE_FREEMARKER_CORE_TEMPLATERESOLVER.length());
+                    } else if (cn.startsWith(ORG_APACHE_FREEMARKER_CORE)) {
+                        return "o.a.f.c." + 
cn.substring(ORG_APACHE_FREEMARKER_CORE.length());
+                    } else if (cn.startsWith(ORG_APACHE_FREEMARKER)) {
+                        return "o.a.f." + 
cn.substring(ORG_APACHE_FREEMARKER.length());
+                    }
+                    // Falls through
+                }
+                return cn;
+            }
+        }
+    }
+
+    /**
+     * Same as {@link #getShortClassNameOfObject(Object, boolean) 
getShortClassNameOfObject(pClass, false)}.
+     */
+    public static String getShortClassNameOfObject(Object obj) {
+        return getShortClassNameOfObject(obj, false);
+    }
+    
+    /**
+     * {@link #getShortClassName(Class, boolean)} called with {@code 
object.getClass()}, but returns the fictional
+     * class name {@code Null} for a {@code null} value.
+     */
+    public static String getShortClassNameOfObject(Object obj, boolean 
shortenFreeMarkerClasses) {
+        if (obj == null) {
+            return "Null";
+        } else {
+            return _ClassUtils.getShortClassName(obj.getClass(), 
shortenFreeMarkerClasses);
+        }
+    }
+
+    /**
+     * Gets the wrapper class for a primitive class, like {@link Integer} for 
{@code int}, also returns {@link Void}
+     * for {@code void}. 
+     * 
+     * @param primitiveClass A {@link Class} like {@code int.type}, {@code 
boolean.type}, etc. If it's not a primitive
+     *     class, or it's {@code null}, then the parameter value is returned 
as is. Note that performance-wise the
+     *     method assumes that it's a primitive class.
+     */
+    public static Class primitiveClassToBoxingClass(Class primitiveClass) {
+        // Tried to sort these with decreasing frequency in API-s:
+        if (primitiveClass == int.class) return Integer.class;
+        if (primitiveClass == boolean.class) return Boolean.class;
+        if (primitiveClass == long.class) return Long.class;
+        if (primitiveClass == double.class) return Double.class;
+        if (primitiveClass == char.class) return Character.class;
+        if (primitiveClass == float.class) return Float.class;
+        if (primitiveClass == byte.class) return Byte.class;
+        if (primitiveClass == short.class) return Short.class;
+        if (primitiveClass == void.class) return Void.class;  // not really a 
primitive, but we normalize it
+        return primitiveClass;
+    }
+
+    /**
+     * The exact reverse of {@link #primitiveClassToBoxingClass}.
+     */
+    public static Class boxingClassToPrimitiveClass(Class boxingClass) {
+        // Tried to sort these with decreasing frequency in API-s:
+        if (boxingClass == Integer.class) return int.class;
+        if (boxingClass == Boolean.class) return boolean.class;
+        if (boxingClass == Long.class) return long.class;
+        if (boxingClass == Double.class) return double.class;
+        if (boxingClass == Character.class) return char.class;
+        if (boxingClass == Float.class) return float.class;
+        if (boxingClass == Byte.class) return byte.class;
+        if (boxingClass == Short.class) return short.class;
+        if (boxingClass == Void.class) return void.class;  // not really a 
primitive, but we normalize to it
+        return boxingClass;
+    }
+    
+    /**
+     * Tells if a type is numerical; works both for primitive types and 
classes.
+     * 
+     * @param type can't be {@code null}
+     */
+    public static boolean isNumerical(Class type) {
+        return Number.class.isAssignableFrom(type)
+                || type.isPrimitive() && type != Boolean.TYPE && type != 
Character.TYPE && type != Void.TYPE;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ebb39b84/freemarker-core/src/main/java/org/apache/freemarker/core/util/_CollectionUtil.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_CollectionUtil.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/util/_CollectionUtil.java
deleted file mode 100644
index af98987..0000000
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/util/_CollectionUtil.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.freemarker.core.util;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Don't use this; used internally by FreeMarker, might changes without notice.
- * {@link Collection} and {@link Map}-related utilities.
- */
-public class _CollectionUtil {
-    
-    private _CollectionUtil() { }
-
-    public static final Object[] EMPTY_OBJECT_ARRAY = new Object[] { };
-    public static final Class[] EMPTY_CLASS_ARRAY = new Class[] { };
-    public static final String[] EMPTY_STRING_ARRAY = new String[] { };
-    public static final char[] EMPTY_CHAR_ARRAY = new char[] { };
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    public static <T> List<? extends T> safeCastList(
-            String argName, List list,
-            Class<T> itemClass, boolean allowNullItem) {
-        if (list == null) {
-            return null;
-        }
-        for (int i = 0; i < list.size(); i++) {
-            Object it = list.get(i);
-            if (!itemClass.isInstance(it)) {
-                if (it == null) {
-                    if (!allowNullItem) {
-                        throw new IllegalArgumentException(
-                                (argName != null ? "Invalid value for argument 
\"" + argName + "\"" : "")
-                                + "List item at index " + i + " is null");
-                    }
-                } else {
-                    throw new IllegalArgumentException(
-                            (argName != null ? "Invalid value for argument \"" 
+ argName + "\"" : "")
-                            + "List item at index " + i + " is not instance of 
" + itemClass.getName() + "; "
-                            + "its class is " + it.getClass().getName() + ".");
-                }
-            }
-        }
-
-        return list;
-    }
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    public static <K, V> Map<? extends K, ? extends V> safeCastMap(
-            String argName, Map map,
-            Class<K> keyClass, boolean allowNullKey,
-            Class<V> valueClass, boolean allowNullValue) {
-        if (map == null) {
-            return null;
-        }
-        for (Map.Entry<?, ?> ent : ((Map<?, ?>) map).entrySet()) {
-            Object key = ent.getKey();
-            if (!keyClass.isInstance(key)) {
-                if (key == null) {
-                    if (!allowNullKey) {
-                        throw new IllegalArgumentException(
-                                (argName != null ? "Invalid value for argument 
\"" + argName + "\": " : "")
-                                        + "The Map contains null key");
-                    }
-                } else {
-                    throw new IllegalArgumentException(
-                            (argName != null ? "Invalid value for argument \"" 
+ argName + "\": " : "")
-                                    + "The Map contains a key that's not 
instance of " + keyClass.getName() +
-                                    "; its class is " + 
key.getClass().getName() + ".");
-                }
-            }
-
-            Object value = ent.getValue();
-            if (!valueClass.isInstance(value)) {
-                if (value == null) {
-                    if (!allowNullValue) {
-                        throw new IllegalArgumentException(
-                                (argName != null ? "Invalid value for argument 
\"" + argName + "\"" : "")
-                                        + "The Map contains null value");
-                    }
-                } else {
-                    throw new IllegalArgumentException(
-                            (argName != null ? "Invalid value for argument \"" 
+ argName + "\"" : "")
-                                    + "The Map contains a value that's not 
instance of " + valueClass.getName() +
-                                    "; its class is " + 
value.getClass().getName() + ".");
-                }
-            }
-        }
-
-        return map;
-    }
-
-    private static final Class<?> UNMODIFIABLE_MAP_CLASS_1 = 
Collections.emptyMap().getClass();
-    private static final Class<?> UNMODIFIABLE_MAP_CLASS_2 = 
Collections.unmodifiableMap(
-            new HashMap<Object, Object> (1)).getClass();
-    private static final Class<?> UNMODIFIABLE_LIST_CLASS_1 = 
Collections.emptyList().getClass();
-    private static final Class<?> UNMODIFIABLE_LIST_CLASS_2 = 
Collections.unmodifiableList(
-            new ArrayList<Object>(1)).getClass();
-
-    public static boolean isMapKnownToBeUnmodifiable(Map<?, ?> map) {
-        if (map == null) {
-            return true;
-        }
-        Class<? extends Map> mapClass = map.getClass();
-        return mapClass == UNMODIFIABLE_MAP_CLASS_1 || mapClass == 
UNMODIFIABLE_MAP_CLASS_2;
-    }
-
-    public static boolean isListKnownToBeUnmodifiable(List<?> list) {
-        if (list == null) {
-            return true;
-        }
-        Class<? extends List> listClass = list.getClass();
-        return listClass == UNMODIFIABLE_LIST_CLASS_1 || listClass == 
UNMODIFIABLE_LIST_CLASS_2;
-    }
-
-    /**
-     * Optimized version of {@link Collections#unmodifiableMap(Map)} (avoids 
needless wrapping).
-     *
-     * @param map The map to return or wrap if not already unmodifiable, or 
{@code null} which is silently bypassed.
-     */
-    public static <K, V> Map<K, V> unmodifiableMap(Map<K, V> map) {
-        return isMapKnownToBeUnmodifiable(map) ? map : 
Collections.unmodifiableMap(map);
-    }
-
-    /**
-     * Adds two {@link Map}-s (keeping the iteration order); assuming the 
inputs are already unmodifiable and
-     * unchanging, it returns an unmodifiable and unchanging {@link Map} 
itself.
-     */
-    public static <K,V> Map<K,V> mergeImmutableMaps(Map<K,V> m1, Map<K,V> m2, 
boolean keepOriginalOrder) {
-        if (m1 == null) return m2;
-        if (m2 == null) return m1;
-        if (m1.isEmpty()) return m2;
-        if (m2.isEmpty()) return m1;
-
-        Map<K, V> mergedM = keepOriginalOrder
-                ? new LinkedHashMap<K, V>((m1.size() + m2.size()) * 4 / 3 + 1, 
0.75f)
-                : new HashMap<K, V>((m1.size() + m2.size()) * 4 / 3 + 1, 
0.75f);
-        mergedM.putAll(m1);
-        if (keepOriginalOrder) {
-            for (K m2Key : m2.keySet()) {
-                mergedM.remove(m2Key); // So that duplicate keys are moved 
after m1 keys
-            }
-        }
-        mergedM.putAll(m2);
-        return Collections.unmodifiableMap(mergedM);
-    }
-
-    /**
-     * Adds multiple {@link List}-s; assuming the inputs are already 
unmodifiable and unchanging, it returns an
-     * unmodifiable and unchanging {@link List} itself.
-     */
-    public static <T> List<T> mergeImmutableLists(boolean 
skipDuplicatesInList1, List<T> ... lists) {
-        if (lists == null || lists.length == 0) {
-            return null;
-        }
-
-        if (lists.length == 1) {
-            return mergeImmutableLists(lists[0], null, skipDuplicatesInList1);
-        } else if (lists.length == 2) {
-            return mergeImmutableLists(lists[0], lists[1], 
skipDuplicatesInList1);
-        } else {
-            List<T> [] reducedLists = new List[lists.length - 1];
-            reducedLists[0] = mergeImmutableLists(lists[0], lists[1], 
skipDuplicatesInList1);
-            System.arraycopy(lists, 2, reducedLists, 1, lists.length - 2);
-            return mergeImmutableLists(skipDuplicatesInList1, reducedLists);
-        }
-    }
-
-    /**
-     * Adds two {@link List}-s; assuming the inputs are already unmodifiable 
and unchanging, it returns an
-     * unmodifiable and unchanging {@link List} itself.
-     */
-    public static <T> List<T> mergeImmutableLists(List<T> list1, List<T> list2,
-            boolean skipDuplicatesInList1) {
-        if (list1 == null) return list2;
-        if (list2 == null) return list1;
-        if (list1.isEmpty()) return list2;
-        if (list2.isEmpty()) return list1;
-
-        ArrayList<T> mergedList = new ArrayList<>(list1.size() + list2.size());
-        if (skipDuplicatesInList1) {
-            Set<T> list2Set = new HashSet<>(list2);
-            for (T it : list1) {
-                if (!list2Set.contains(it)) {
-                    mergedList.add(it);
-                }
-            }
-        } else {
-            mergedList.addAll(list1);
-        }
-        mergedList.addAll(list2);
-        return Collections.unmodifiableList(mergedList);
-    }
-
-}

Reply via email to