http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/BeansWrapperConfiguration.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/BeansWrapperConfiguration.java
 
b/src/main/java/org/apache/freemarker/core/model/impl/beans/BeansWrapperConfiguration.java
deleted file mode 100644
index 94997cb..0000000
--- 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/BeansWrapperConfiguration.java
+++ /dev/null
@@ -1,232 +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.model.impl.beans;
-
-import org.apache.freemarker.core.Version;
-import org.apache.freemarker.core._CoreAPI;
-import org.apache.freemarker.core.model.ObjectWrapper;
-import org.apache.freemarker.core.model.TemplateDateModel;
-import org.apache.freemarker.core.model.impl.DefaultObjectWrapperBuilder;
-
-/**
- * Holds {@link BeansWrapper} configuration settings and defines their 
defaults.
- * You will not use this abstract class directly, but concrete subclasses like 
{@link BeansWrapperBuilder} and
- * {@link DefaultObjectWrapperBuilder}. Unless, you are developing a builder 
for a custom {@link BeansWrapper} subclass.
- * 
- * <p>This class is designed so that its instances can be used as lookup keys 
in a singleton cache. This is also why
- * this class defines the configuration setting defaults for {@link 
BeansWrapper}, instead of leaving that to
- * {@link BeansWrapper} itself. (Because, the default values influence the 
lookup key, and the singleton needs to be
- * looked up without creating a {@link BeansWrapper} instance.) However, 
because instances are mutable, you should
- * deep-clone it with {@link #clone(boolean)} before using it as cache key.
- * 
- * @since 2.3.21
- */
-public abstract class BeansWrapperConfiguration implements Cloneable {
-
-    private final Version incompatibleImprovements;
-    
-    protected ClassIntrospectorBuilder classIntrospectorFactory;
-    
-    // Properties and their *defaults*:
-    private boolean simpleMapWrapper = false;
-    private int defaultDateType = TemplateDateModel.UNKNOWN;
-    private ObjectWrapper outerIdentity = null;
-    private boolean strict = false;
-    private boolean useModelCache = false;
-    // Attention!
-    // - As this object is a cache key, non-normalized field values should be 
avoided.
-    // - Fields with default values must be set until the end of the 
constructor to ensure that when the lookup happens,
-    //   there will be no unset fields.
-    // - If you add a new field, review all methods in this class
-    
-    /**
-     * @param incompatibleImprovements
-     *            See the corresponding parameter of {@link 
BeansWrapper#BeansWrapper(Version)}. Not {@code null}. Note
-     *            that the version will be normalized to the lowest version 
where the same incompatible
-     *            {@link BeansWrapper} improvements were already present, so 
for the returned instance
-     *            {@link #getIncompatibleImprovements()} might returns a lower 
version than what you have specified
-     *            here.
-     * @param isIncompImprsAlreadyNormalized
-     *            Tells if the {@code incompatibleImprovements} parameter 
contains an <em>already normalized</em> value.
-     *            This parameter meant to be {@code true} when the class that 
extends {@link BeansWrapper} needs to add
-     *            additional breaking versions over those of {@link 
BeansWrapper}. Thus, if this parameter is
-     *            {@code true}, the versions where {@link BeansWrapper} had 
breaking changes must be already factored
-     *            into the {@code incompatibleImprovements} parameter value, 
as no more normalization will happen. (You
-     *            can use {@link 
BeansWrapper#normalizeIncompatibleImprovementsVersion(Version)} to discover 
those.)
-     * 
-     * @since 2.3.22
-     */
-    protected BeansWrapperConfiguration(Version incompatibleImprovements, 
boolean isIncompImprsAlreadyNormalized) {
-        _CoreAPI.checkVersionNotNullAndSupported(incompatibleImprovements);
-        
-        incompatibleImprovements = isIncompImprsAlreadyNormalized
-                ? incompatibleImprovements
-                : 
BeansWrapper.normalizeIncompatibleImprovementsVersion(incompatibleImprovements);
-        this.incompatibleImprovements = incompatibleImprovements;
-        
-        classIntrospectorFactory = new 
ClassIntrospectorBuilder(incompatibleImprovements);
-    }
-    
-    /**
-     * Same as {@link #BeansWrapperConfiguration(Version, boolean) 
BeansWrapperConfiguration(Version, false)}.
-     */
-    protected BeansWrapperConfiguration(Version incompatibleImprovements) {
-        this(incompatibleImprovements, false);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + incompatibleImprovements.hashCode();
-        result = prime * result + (simpleMapWrapper ? 1231 : 1237);
-        result = prime * result + defaultDateType;
-        result = prime * result + (outerIdentity != null ? 
outerIdentity.hashCode() : 0);
-        result = prime * result + (strict ? 1231 : 1237);
-        result = prime * result + (useModelCache ? 1231 : 1237);
-        result = prime * result + classIntrospectorFactory.hashCode();
-        return result;
-    }
-
-    /**
-     * Two {@link BeansWrapperConfiguration}-s are equal exactly if their 
classes are identical ({@code ==}), and their
-     * field values are equal.
-     */
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) return true;
-        if (obj == null) return false;
-        if (getClass() != obj.getClass()) return false;
-        BeansWrapperConfiguration other = (BeansWrapperConfiguration) obj;
-        
-        if (!incompatibleImprovements.equals(other.incompatibleImprovements)) 
return false;
-        if (simpleMapWrapper != other.simpleMapWrapper) return false;
-        if (defaultDateType != other.defaultDateType) return false;
-        if (outerIdentity != other.outerIdentity) return false;
-        if (strict != other.strict) return false;
-        if (useModelCache != other.useModelCache) return false;
-        return classIntrospectorFactory.equals(other.classIntrospectorFactory);
-    }
-    
-    protected Object clone(boolean deepCloneKey) {
-        try {
-            BeansWrapperConfiguration clone = (BeansWrapperConfiguration) 
super.clone();
-            if (deepCloneKey) {
-                clone.classIntrospectorFactory
-                        = (ClassIntrospectorBuilder) 
classIntrospectorFactory.clone();
-            }
-            return clone;
-        } catch (CloneNotSupportedException e) {
-            throw new RuntimeException("Failed to clone 
BeansWrapperConfiguration", e);
-        }
-    }
-    
-    public boolean isSimpleMapWrapper() {
-        return simpleMapWrapper;
-    }
-
-    /** See {@link BeansWrapper#setSimpleMapWrapper(boolean)}. */
-    public void setSimpleMapWrapper(boolean simpleMapWrapper) {
-        this.simpleMapWrapper = simpleMapWrapper;
-    }
-
-    public int getDefaultDateType() {
-        return defaultDateType;
-    }
-
-    /** See {@link BeansWrapper#setDefaultDateType(int)}. */
-    public void setDefaultDateType(int defaultDateType) {
-        this.defaultDateType = defaultDateType;
-    }
-
-    public ObjectWrapper getOuterIdentity() {
-        return outerIdentity;
-    }
-
-    /**
-     * See {@link BeansWrapper#setOuterIdentity(ObjectWrapper)}, except here 
the default is {@code null} that means
-     * the {@link ObjectWrapper} that you will set up with this {@link 
BeansWrapperBuilder} object.
-     */
-    public void setOuterIdentity(ObjectWrapper outerIdentity) {
-        this.outerIdentity = outerIdentity;
-    }
-
-    public boolean isStrict() {
-        return strict;
-    }
-
-    /** See {@link BeansWrapper#setStrict(boolean)}. */
-    public void setStrict(boolean strict) {
-        this.strict = strict;
-    }
-
-    public boolean getUseModelCache() {
-        return useModelCache;
-    }
-
-    /** See {@link BeansWrapper#setUseModelCache(boolean)} (it means the 
same). */
-    public void setUseModelCache(boolean useModelCache) {
-        this.useModelCache = useModelCache;
-    }
-
-    public Version getIncompatibleImprovements() {
-        return incompatibleImprovements;
-    }
-    
-    public int getExposureLevel() {
-        return classIntrospectorFactory.getExposureLevel();
-    }
-
-    /** See {@link BeansWrapper#setExposureLevel(int)}. */
-    public void setExposureLevel(int exposureLevel) {
-        classIntrospectorFactory.setExposureLevel(exposureLevel);
-    }
-
-    public boolean getExposeFields() {
-        return classIntrospectorFactory.getExposeFields();
-    }
-
-    /** See {@link BeansWrapper#setExposeFields(boolean)}. */
-    public void setExposeFields(boolean exposeFields) {
-        classIntrospectorFactory.setExposeFields(exposeFields);
-    }
-
-    public MethodAppearanceFineTuner getMethodAppearanceFineTuner() {
-        return classIntrospectorFactory.getMethodAppearanceFineTuner();
-    }
-
-    /**
-     * See {@link 
BeansWrapper#setMethodAppearanceFineTuner(MethodAppearanceFineTuner)}; 
additionally,
-     * note that currently setting this to non-{@code null} will disable class 
introspection cache sharing, unless
-     * the value implements {@link SingletonCustomizer}.
-     */
-    public void setMethodAppearanceFineTuner(MethodAppearanceFineTuner 
methodAppearanceFineTuner) {
-        
classIntrospectorFactory.setMethodAppearanceFineTuner(methodAppearanceFineTuner);
-    }
-
-    MethodSorter getMethodSorter() {
-        return classIntrospectorFactory.getMethodSorter();
-    }
-
-    void setMethodSorter(MethodSorter methodSorter) {
-        classIntrospectorFactory.setMethodSorter(methodSorter);
-    }
- 
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/BooleanModel.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/BooleanModel.java 
b/src/main/java/org/apache/freemarker/core/model/impl/beans/BooleanModel.java
deleted file mode 100644
index 857df36..0000000
--- 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/BooleanModel.java
+++ /dev/null
@@ -1,40 +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.model.impl.beans;
-
-import org.apache.freemarker.core.model.TemplateBooleanModel;
-
-/**
- * <p>A class that will wrap instances of {@link java.lang.Boolean} into a
- * {@link TemplateBooleanModel}.
- */
-public class BooleanModel extends BeanModel implements TemplateBooleanModel {
-    private final boolean value;
-    
-    public BooleanModel(Boolean bool, BeansWrapper wrapper) {
-        super(bool, wrapper, false);
-        value = bool.booleanValue();
-    }
-
-    @Override
-    public boolean getAsBoolean() {
-        return value;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/CallableMemberDescriptor.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/CallableMemberDescriptor.java
 
b/src/main/java/org/apache/freemarker/core/model/impl/beans/CallableMemberDescriptor.java
deleted file mode 100644
index fb55571..0000000
--- 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/CallableMemberDescriptor.java
+++ /dev/null
@@ -1,56 +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.model.impl.beans;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateModelException;
-
-/**
- * Packs a {@link Method} or {@link Constructor} together with its parameter 
types. The actual
- * {@link Method} or {@link Constructor} is not exposed by the API, because in 
rare cases calling them require
- * type conversion that the Java reflection API can't do, hence the developer 
shouldn't be tempted to call them
- * directly. 
- */
-abstract class CallableMemberDescriptor extends 
MaybeEmptyCallableMemberDescriptor {
-
-    abstract TemplateModel invokeMethod(BeansWrapper bw, Object obj, Object[] 
args)
-            throws TemplateModelException, InvocationTargetException, 
IllegalAccessException;
-
-    abstract Object invokeConstructor(BeansWrapper bw, Object[] args)
-            throws IllegalArgumentException, InstantiationException, 
IllegalAccessException, InvocationTargetException,
-            TemplateModelException;
-    
-    abstract String getDeclaration();
-    
-    abstract boolean isConstructor();
-    
-    abstract boolean isStatic();
-
-    abstract boolean isVarargs();
-
-    abstract Class[] getParamTypes();
-
-    abstract String getName();
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/CharacterOrString.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/CharacterOrString.java
 
b/src/main/java/org/apache/freemarker/core/model/impl/beans/CharacterOrString.java
deleted file mode 100644
index 4bd297b..0000000
--- 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/CharacterOrString.java
+++ /dev/null
@@ -1,45 +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.model.impl.beans;
-
-import org.apache.freemarker.core.model.TemplateScalarModel;
-
-/**
- * Represents value unwrapped both to {@link Character} and {@link String}. 
This is needed for unwrapped overloaded
- * method parameters where both {@link Character} and {@link String} occurs on 
the same parameter position when the
- * {@link TemplateScalarModel} to unwrapp contains a {@link String} of length 
1.
- */
-final class CharacterOrString {
-
-    private final String stringValue;
-
-    CharacterOrString(String stringValue) {
-        this.stringValue = stringValue;
-    }
-    
-    String getAsString() {
-        return stringValue;
-    }
-
-    char getAsChar() {
-        return stringValue.charAt(0);
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/ClassBasedModelFactory.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/ClassBasedModelFactory.java
 
b/src/main/java/org/apache/freemarker/core/model/impl/beans/ClassBasedModelFactory.java
deleted file mode 100644
index 1fd4d61..0000000
--- 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/ClassBasedModelFactory.java
+++ /dev/null
@@ -1,148 +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.model.impl.beans;
-
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.apache.freemarker.core.model.TemplateHashModel;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateModelException;
-import org.apache.freemarker.core.util._ClassUtil;
-
-/**
- * Base class for hash models keyed by Java class names. 
- */
-abstract class ClassBasedModelFactory implements TemplateHashModel {
-    private final BeansWrapper wrapper;
-    
-    private final Map/*<String,TemplateModel>*/ cache = new 
ConcurrentHashMap();
-    private final Set classIntrospectionsInProgress = new HashSet();
-    
-    protected ClassBasedModelFactory(BeansWrapper wrapper) {
-        this.wrapper = wrapper;
-    }
-
-    @Override
-    public TemplateModel get(String key) throws TemplateModelException {
-        try {
-            return getInternal(key);
-        } catch (Exception e) {
-            if (e instanceof TemplateModelException) {
-                throw (TemplateModelException) e;
-            } else {
-                throw new TemplateModelException(e);
-            }
-        }
-    }
-
-    private TemplateModel getInternal(String key) throws 
TemplateModelException, ClassNotFoundException {
-        {
-            TemplateModel model = (TemplateModel) cache.get(key);
-            if (model != null) return model;
-        }
-
-        final ClassIntrospector classIntrospector;
-        int classIntrospectorClearingCounter;
-        final Object sharedLock = wrapper.getSharedIntrospectionLock();
-        synchronized (sharedLock) {
-            TemplateModel model = (TemplateModel) cache.get(key);
-            if (model != null) return model;
-            
-            while (model == null
-                    && classIntrospectionsInProgress.contains(key)) {
-                // Another thread is already introspecting this class;
-                // waiting for its result.
-                try {
-                    sharedLock.wait();
-                    model = (TemplateModel) cache.get(key);
-                } catch (InterruptedException e) {
-                    throw new RuntimeException(
-                            "Class inrospection data lookup aborded: " + e);
-                }
-            }
-            if (model != null) return model;
-            
-            // This will be the thread that introspects this class.
-            classIntrospectionsInProgress.add(key);
-
-            // While the classIntrospector should not be changed from another 
thread, badly written apps can do that,
-            // and it's cheap to get the classIntrospector from inside the 
lock here:   
-            classIntrospector = wrapper.getClassIntrospector();
-            classIntrospectorClearingCounter = 
classIntrospector.getClearingCounter();
-        }
-        try {
-            final Class clazz = _ClassUtil.forName(key);
-            
-            // This is called so that we trigger the
-            // class-reloading detector. If clazz is a reloaded class,
-            // the wrapper will in turn call our clearCache method.
-            // TODO: Why do we check it now and only now?
-            classIntrospector.get(clazz);
-            
-            TemplateModel model = createModel(clazz);
-            // Warning: model will be null if the class is not good for the 
subclass.
-            // For example, EnumModels#createModel returns null if clazz is 
not an enum.
-            
-            if (model != null) {
-                synchronized (sharedLock) {
-                    // Save it into the cache, but only if nothing relevant 
has changed while we were outside the lock: 
-                    if (classIntrospector == wrapper.getClassIntrospector()
-                            && classIntrospectorClearingCounter == 
classIntrospector.getClearingCounter()) {  
-                        cache.put(key, model);
-                    }
-                }
-            }
-            return model;
-        } finally {
-            synchronized (sharedLock) {
-                classIntrospectionsInProgress.remove(key);
-                sharedLock.notifyAll();
-            }
-        }
-    }
-    
-    void clearCache() {
-        synchronized (wrapper.getSharedIntrospectionLock()) {
-            cache.clear();
-        }
-    }
-    
-    void removeFromCache(Class clazz) {
-        synchronized (wrapper.getSharedIntrospectionLock()) {
-            cache.remove(clazz.getName());
-        }
-    }
-
-    @Override
-    public boolean isEmpty() {
-        return false;
-    }
-    
-    protected abstract TemplateModel createModel(Class clazz) 
-    throws TemplateModelException;
-    
-    protected BeansWrapper getWrapper() {
-        return wrapper;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/ClassChangeNotifier.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/ClassChangeNotifier.java
 
b/src/main/java/org/apache/freemarker/core/model/impl/beans/ClassChangeNotifier.java
deleted file mode 100644
index f85fafd..0000000
--- 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/ClassChangeNotifier.java
+++ /dev/null
@@ -1,32 +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.model.impl.beans;
-
-/**
- * Reports when the non-private interface of a class was changed to the 
subscribers.   
- */
-interface ClassChangeNotifier {
-    
-    /**
-     * @param classIntrospector Should only be weak-referenced from the 
monitor object.
-     */
-    void subscribe(ClassIntrospector classIntrospector);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/ClassIntrospector.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/ClassIntrospector.java
 
b/src/main/java/org/apache/freemarker/core/model/impl/beans/ClassIntrospector.java
deleted file mode 100644
index d1cf191..0000000
--- 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/ClassIntrospector.java
+++ /dev/null
@@ -1,808 +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.model.impl.beans;
-
-import java.beans.BeanInfo;
-import java.beans.IndexedPropertyDescriptor;
-import java.beans.IntrospectionException;
-import java.beans.Introspector;
-import java.beans.MethodDescriptor;
-import java.beans.PropertyDescriptor;
-import java.lang.ref.Reference;
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.WeakReference;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.apache.freemarker.core._CoreLogs;
-import 
org.apache.freemarker.core.model.impl.beans.BeansWrapper.MethodAppearanceDecision;
-import 
org.apache.freemarker.core.model.impl.beans.BeansWrapper.MethodAppearanceDecisionInput;
-import org.apache.freemarker.core.util.BugException;
-import org.apache.freemarker.core.util._NullArgumentException;
-import org.slf4j.Logger;
-
-/**
- * Returns information about a {@link Class} that's useful for FreeMarker. 
Encapsulates a cache for this. Thread-safe,
- * doesn't even require "proper publishing" starting from 2.3.24 or Java 5. 
Immutable, with the exception of the
- * internal caches.
- * 
- * <p>
- * Note that instances of this are cached on the level of FreeMarker's 
defining class loader. Hence, it must not do
- * operations that depend on the Thread Context Class Loader, such as 
resolving class names.
- */
-class ClassIntrospector {
-
-    // Attention: This class must be thread-safe (not just after proper 
publishing). This is important as some of
-    // these are shared by many object wrappers, and concurrency related 
glitches due to user errors must remain
-    // local to the object wrappers, not corrupting the shared 
ClassIntrospector.
-
-    private static final Logger LOG = _CoreLogs.BEANS_WRAPPER;
-
-    private static final String JREBEL_SDK_CLASS_NAME = 
"org.zeroturnaround.javarebel.ClassEventListener";
-    private static final String JREBEL_INTEGRATION_ERROR_MSG
-            = "Error initializing JRebel integration. JRebel integration 
disabled.";
-
-    private static final ClassChangeNotifier CLASS_CHANGE_NOTIFIER;
-    static {
-        boolean jRebelAvailable;
-        try {
-            Class.forName(JREBEL_SDK_CLASS_NAME);
-            jRebelAvailable = true;
-        } catch (Throwable e) {
-            jRebelAvailable = false;
-            try {
-                if (!(e instanceof ClassNotFoundException)) {
-                    LOG.error(JREBEL_INTEGRATION_ERROR_MSG, e);
-                }
-            } catch (Throwable loggingE) {
-                // ignore
-            }
-        }
-
-        ClassChangeNotifier classChangeNotifier;
-        if (jRebelAvailable) {
-            try {
-                classChangeNotifier = (ClassChangeNotifier)
-                        
Class.forName("org.apache.freemarker.core.model.impl.beans.JRebelClassChangeNotifier").newInstance();
-            } catch (Throwable e) {
-                classChangeNotifier = null;
-                try {
-                    LOG.error(JREBEL_INTEGRATION_ERROR_MSG, e);
-                } catch (Throwable loggingE) {
-                    // ignore
-                }
-            }
-        } else {
-            classChangeNotifier = null;
-        }
-
-        CLASS_CHANGE_NOTIFIER = classChangeNotifier;
-    }
-
-    // 
-----------------------------------------------------------------------------------------------------------------
-    // Introspection info Map keys:
-
-    /** Key in the class info Map to the Map that maps method to argument type 
arrays */
-    private static final Object ARG_TYPES_BY_METHOD_KEY = new Object();
-    /** Key in the class info Map to the object that represents the 
constructors (one or multiple due to overloading) */
-    static final Object CONSTRUCTORS_KEY = new Object();
-    /** Key in the class info Map to the get(String|Object) Method */
-    static final Object GENERIC_GET_KEY = new Object();
-
-    // 
-----------------------------------------------------------------------------------------------------------------
-    // Introspection configuration properties:
-
-    // Note: These all must be *declared* final (or else synchronization is 
needed everywhere where they are accessed).
-
-    final int exposureLevel;
-    final boolean exposeFields;
-    final MethodAppearanceFineTuner methodAppearanceFineTuner;
-    final MethodSorter methodSorter;
-
-    /** See {@link #getHasSharedInstanceRestrictons()} */
-    final private boolean hasSharedInstanceRestrictons;
-
-    /** See {@link #isShared()} */
-    final private boolean shared;
-
-    // 
-----------------------------------------------------------------------------------------------------------------
-    // State fields:
-
-    private final Object sharedLock;
-    private final Map<Class<?>, Map<Object, Object>> cache
-            = new ConcurrentHashMap<>(0, 0.75f, 16);
-    private final Set<String> cacheClassNames = new HashSet<>(0);
-    private final Set<Class<?>> classIntrospectionsInProgress = new 
HashSet<>(0);
-
-    private final 
List<WeakReference<Object/*ClassBasedModelFactory|ModelCache>*/>> modelFactories
-            = new LinkedList<>();
-    private final ReferenceQueue<Object> modelFactoriesRefQueue = new 
ReferenceQueue<>();
-
-    private int clearingCounter;
-
-    // 
-----------------------------------------------------------------------------------------------------------------
-    // Instantiation:
-
-    /**
-     * Creates a new instance, that is hence surely not shared (singleton) 
instance.
-     * 
-     * @param pa
-     *            Stores what the values of the JavaBean properties of the 
returned instance will be. Not {@code null}.
-     */
-    ClassIntrospector(ClassIntrospectorBuilder pa, Object sharedLock) {
-        this(pa, sharedLock, false, false);
-    }
-
-    /**
-     * @param hasSharedInstanceRestrictons
-     *            {@code true} exactly if we are creating a new instance with 
{@link ClassIntrospectorBuilder}. Then
-     *            it's {@code true} even if it won't put the instance into the 
cache.
-     */
-    ClassIntrospector(ClassIntrospectorBuilder builder, Object sharedLock,
-            boolean hasSharedInstanceRestrictons, boolean shared) {
-        _NullArgumentException.check("sharedLock", sharedLock);
-
-        exposureLevel = builder.getExposureLevel();
-        exposeFields = builder.getExposeFields();
-        methodAppearanceFineTuner = builder.getMethodAppearanceFineTuner();
-        methodSorter = builder.getMethodSorter();
-
-        this.sharedLock = sharedLock;
-
-        this.hasSharedInstanceRestrictons = hasSharedInstanceRestrictons;
-        this.shared = shared;
-
-        if (CLASS_CHANGE_NOTIFIER != null) {
-            CLASS_CHANGE_NOTIFIER.subscribe(this);
-        }
-    }
-
-    /**
-     * Returns a {@link ClassIntrospectorBuilder}-s that could be used to 
create an identical {@link #ClassIntrospector}
-     * . The returned {@link ClassIntrospectorBuilder} can be modified without 
interfering with anything.
-     */
-    ClassIntrospectorBuilder getPropertyAssignments() {
-        return new ClassIntrospectorBuilder(this);
-    }
-
-    // 
------------------------------------------------------------------------------------------------------------------
-    // Introspection:
-
-    /**
-     * Gets the class introspection data from {@link #cache}, automatically 
creating the cache entry if it's missing.
-     * 
-     * @return A {@link Map} where each key is a property/method/field name 
(or a special {@link Object} key like
-     *         {@link #CONSTRUCTORS_KEY}), each value is a {@link 
PropertyDescriptor} or {@link Method} or
-     *         {@link OverloadedMethods} or {@link Field} (but better check 
the source code...).
-     */
-    Map<Object, Object> get(Class<?> clazz) {
-        {
-            Map<Object, Object> introspData = cache.get(clazz);
-            if (introspData != null) return introspData;
-        }
-
-        String className;
-        synchronized (sharedLock) {
-            Map<Object, Object> introspData = cache.get(clazz);
-            if (introspData != null) return introspData;
-
-            className = clazz.getName();
-            if (cacheClassNames.contains(className)) {
-                onSameNameClassesDetected(className);
-            }
-
-            while (introspData == null && 
classIntrospectionsInProgress.contains(clazz)) {
-                // Another thread is already introspecting this class;
-                // waiting for its result.
-                try {
-                    sharedLock.wait();
-                    introspData = cache.get(clazz);
-                } catch (InterruptedException e) {
-                    throw new RuntimeException(
-                            "Class inrospection data lookup aborded: " + e);
-                }
-            }
-            if (introspData != null) return introspData;
-
-            // This will be the thread that introspects this class.
-            classIntrospectionsInProgress.add(clazz);
-        }
-        try {
-            Map<Object, Object> introspData = 
createClassIntrospectionData(clazz);
-            synchronized (sharedLock) {
-                cache.put(clazz, introspData);
-                cacheClassNames.add(className);
-            }
-            return introspData;
-        } finally {
-            synchronized (sharedLock) {
-                classIntrospectionsInProgress.remove(clazz);
-                sharedLock.notifyAll();
-            }
-        }
-    }
-
-    /**
-     * Creates a {@link Map} with the content as described for the return 
value of {@link #get(Class)}.
-     */
-    private Map<Object, Object> createClassIntrospectionData(Class<?> clazz) {
-        final Map<Object, Object> introspData = new HashMap<>();
-
-        if (exposeFields) {
-            addFieldsToClassIntrospectionData(introspData, clazz);
-        }
-
-        final Map<MethodSignature, List<Method>> accessibleMethods = 
discoverAccessibleMethods(clazz);
-
-        addGenericGetToClassIntrospectionData(introspData, accessibleMethods);
-
-        if (exposureLevel != BeansWrapper.EXPOSE_NOTHING) {
-            try {
-                addBeanInfoToClassIntrospectionData(introspData, clazz, 
accessibleMethods);
-            } catch (IntrospectionException e) {
-                LOG.warn("Couldn't properly perform introspection for class 
{}", clazz.getName(), e);
-                introspData.clear(); // FIXME NBC: Don't drop everything here.
-            }
-        }
-
-        addConstructorsToClassIntrospectionData(introspData, clazz);
-
-        if (introspData.size() > 1) {
-            return introspData;
-        } else if (introspData.size() == 0) {
-            return Collections.emptyMap();
-        } else { // map.size() == 1
-            Entry<Object, Object> e = introspData.entrySet().iterator().next();
-            return Collections.singletonMap(e.getKey(), e.getValue());
-        }
-    }
-
-    private void addFieldsToClassIntrospectionData(Map<Object, Object> 
introspData, Class<?> clazz)
-            throws SecurityException {
-        for (Field field : clazz.getFields()) {
-            if ((field.getModifiers() & Modifier.STATIC) == 0) {
-                introspData.put(field.getName(), field);
-            }
-        }
-    }
-
-    private void addBeanInfoToClassIntrospectionData(
-            Map<Object, Object> introspData, Class<?> clazz, 
Map<MethodSignature, List<Method>> accessibleMethods)
-            throws IntrospectionException {
-        BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
-
-        PropertyDescriptor[] pda = beanInfo.getPropertyDescriptors();
-        if (pda != null) {
-            int pdaLength = pda.length;
-            for (int i = pdaLength - 1; i >= 0; --i) {
-                addPropertyDescriptorToClassIntrospectionData(
-                        introspData, pda[i], clazz,
-                        accessibleMethods);
-            }
-        }
-
-        if (exposureLevel < BeansWrapper.EXPOSE_PROPERTIES_ONLY) {
-            final MethodAppearanceDecision decision = new 
MethodAppearanceDecision();
-            MethodAppearanceDecisionInput decisionInput = null;
-            final MethodDescriptor[] mda = 
sortMethodDescriptors(beanInfo.getMethodDescriptors());
-            if (mda != null) {
-                int mdaLength = mda.length;
-                for (int i = mdaLength - 1; i >= 0; --i) {
-                    final MethodDescriptor md = mda[i];
-                    final Method method = 
getMatchingAccessibleMethod(md.getMethod(), accessibleMethods);
-                    if (method != null && isAllowedToExpose(method)) {
-                        decision.setDefaults(method);
-                        if (methodAppearanceFineTuner != null) {
-                            if (decisionInput == null) {
-                                decisionInput = new 
MethodAppearanceDecisionInput();
-                            }
-                            decisionInput.setContainingClass(clazz);
-                            decisionInput.setMethod(method);
-    
-                            methodAppearanceFineTuner.process(decisionInput, 
decision);
-                        }
-    
-                        PropertyDescriptor propDesc = 
decision.getExposeAsProperty();
-                        if (propDesc != null && 
!(introspData.get(propDesc.getName()) instanceof PropertyDescriptor)) {
-                            addPropertyDescriptorToClassIntrospectionData(
-                                    introspData, propDesc, clazz, 
accessibleMethods);
-                        }
-    
-                        String methodKey = decision.getExposeMethodAs();
-                        if (methodKey != null) {
-                            Object previous = introspData.get(methodKey);
-                            if (previous instanceof Method) {
-                                // Overloaded method - replace Method with a 
OverloadedMethods
-                                OverloadedMethods overloadedMethods = new 
OverloadedMethods();
-                                overloadedMethods.addMethod((Method) previous);
-                                overloadedMethods.addMethod(method);
-                                introspData.put(methodKey, overloadedMethods);
-                                // Remove parameter type information
-                                
getArgTypesByMethod(introspData).remove(previous);
-                            } else if (previous instanceof OverloadedMethods) {
-                                // Already overloaded method - add new overload
-                                ((OverloadedMethods) 
previous).addMethod(method);
-                            } else if (decision.getMethodShadowsProperty()
-                                    || !(previous instanceof 
PropertyDescriptor)) {
-                                // Simple method (this far)
-                                introspData.put(methodKey, method);
-                                getArgTypesByMethod(introspData).put(method,
-                                        method.getParameterTypes());
-                            }
-                        }
-                    }
-                } // for each in mda
-            } // if mda != null
-        } // end if (exposureLevel < EXPOSE_PROPERTIES_ONLY)
-    }
-
-    private void addPropertyDescriptorToClassIntrospectionData(Map<Object, 
Object> introspData,
-            PropertyDescriptor pd, Class<?> clazz, Map<MethodSignature, 
List<Method>> accessibleMethods) {
-        if (pd instanceof IndexedPropertyDescriptor) {
-            IndexedPropertyDescriptor ipd =
-                    (IndexedPropertyDescriptor) pd;
-            Method readMethod = ipd.getIndexedReadMethod();
-            Method publicReadMethod = getMatchingAccessibleMethod(readMethod, 
accessibleMethods);
-            if (publicReadMethod != null && 
isAllowedToExpose(publicReadMethod)) {
-                try {
-                    if (readMethod != publicReadMethod) {
-                        ipd = new IndexedPropertyDescriptor(
-                                ipd.getName(), ipd.getReadMethod(),
-                                null, publicReadMethod,
-                                null);
-                    }
-                    introspData.put(ipd.getName(), ipd);
-                    getArgTypesByMethod(introspData).put(publicReadMethod, 
publicReadMethod.getParameterTypes());
-                } catch (IntrospectionException e) {
-                    LOG.warn("Failed creating a publicly-accessible property 
descriptor "
-                            + "for {} indexed property {}, read method {}",
-                            clazz.getName(), pd.getName(), publicReadMethod,
-                            e);
-                }
-            }
-        } else {
-            Method readMethod = pd.getReadMethod();
-            Method publicReadMethod = getMatchingAccessibleMethod(readMethod, 
accessibleMethods);
-            if (publicReadMethod != null && 
isAllowedToExpose(publicReadMethod)) {
-                try {
-                    if (readMethod != publicReadMethod) {
-                        pd = new PropertyDescriptor(pd.getName(), 
publicReadMethod, null);
-                        pd.setReadMethod(publicReadMethod);
-                    }
-                    introspData.put(pd.getName(), pd);
-                } catch (IntrospectionException e) {
-                    LOG.warn("Failed creating a publicly-accessible property 
descriptor "
-                            + "for {} property {}, read method {}",
-                            clazz.getName(), pd.getName(), publicReadMethod,
-                            e);
-                }
-            }
-        }
-    }
-
-    private void addGenericGetToClassIntrospectionData(Map<Object, Object> 
introspData,
-            Map<MethodSignature, List<Method>> accessibleMethods) {
-        Method genericGet = getFirstAccessibleMethod(
-                MethodSignature.GET_STRING_SIGNATURE, accessibleMethods);
-        if (genericGet == null) {
-            genericGet = getFirstAccessibleMethod(
-                    MethodSignature.GET_OBJECT_SIGNATURE, accessibleMethods);
-        }
-        if (genericGet != null) {
-            introspData.put(GENERIC_GET_KEY, genericGet);
-        }
-    }
-
-    private void addConstructorsToClassIntrospectionData(final Map<Object, 
Object> introspData,
-            Class<?> clazz) {
-        try {
-            Constructor<?>[] ctors = clazz.getConstructors();
-            if (ctors.length == 1) {
-                Constructor<?> ctor = ctors[0];
-                introspData.put(CONSTRUCTORS_KEY, new SimpleMethod(ctor, 
ctor.getParameterTypes()));
-            } else if (ctors.length > 1) {
-                OverloadedMethods overloadedCtors = new OverloadedMethods();
-                for (Constructor<?> ctor : ctors) {
-                    overloadedCtors.addConstructor(ctor);
-                }
-                introspData.put(CONSTRUCTORS_KEY, overloadedCtors);
-            }
-        } catch (SecurityException e) {
-            LOG.warn("Can't discover constructors for class {}", 
clazz.getName(), e);
-        }
-    }
-
-    /**
-     * Retrieves mapping of {@link MethodSignature}-s to a {@link List} of 
accessible methods for a class. In case the
-     * class is not public, retrieves methods with same signature as its 
public methods from public superclasses and
-     * interfaces. Basically upcasts every method to the nearest accessible 
method.
-     */
-    private static Map<MethodSignature, List<Method>> 
discoverAccessibleMethods(Class<?> clazz) {
-        Map<MethodSignature, List<Method>> accessibles = new HashMap<>();
-        discoverAccessibleMethods(clazz, accessibles);
-        return accessibles;
-    }
-
-    private static void discoverAccessibleMethods(Class<?> clazz, 
Map<MethodSignature, List<Method>> accessibles) {
-        if (Modifier.isPublic(clazz.getModifiers())) {
-            try {
-                Method[] methods = clazz.getMethods();
-                for (Method method : methods) {
-                    MethodSignature sig = new MethodSignature(method);
-                    // Contrary to intuition, a class can actually have several
-                    // different methods with same signature *but* different
-                    // return types. These can't be constructed using Java the
-                    // language, as this is illegal on source code level, but
-                    // the compiler can emit synthetic methods as part of
-                    // generic type reification that will have same signature
-                    // yet different return type than an existing explicitly
-                    // declared method. Consider:
-                    // public interface I<T> { T m(); }
-                    // public class C implements I<Integer> { Integer m() { 
return 42; } }
-                    // C.class will have both "Object m()" and "Integer m()" 
methods.
-                    List<Method> methodList = accessibles.get(sig);
-                    if (methodList == null) {
-                        // TODO Collection.singletonList is more efficient, 
though read only.
-                        methodList = new LinkedList<>();
-                        accessibles.put(sig, methodList);
-                    }
-                    methodList.add(method);
-                }
-                return;
-            } catch (SecurityException e) {
-                LOG.warn("Could not discover accessible methods of class {}, 
attemping superclasses/interfaces.",
-                        clazz.getName(), e);
-                // Fall through and attempt to discover superclass/interface 
methods
-            }
-        }
-
-        Class<?>[] interfaces = clazz.getInterfaces();
-        for (Class<?> anInterface : interfaces) {
-            discoverAccessibleMethods(anInterface, accessibles);
-        }
-        Class<?> superclass = clazz.getSuperclass();
-        if (superclass != null) {
-            discoverAccessibleMethods(superclass, accessibles);
-        }
-    }
-
-    private static Method getMatchingAccessibleMethod(Method m, 
Map<MethodSignature, List<Method>> accessibles) {
-        if (m == null) {
-            return null;
-        }
-        MethodSignature sig = new MethodSignature(m);
-        List<Method> ams = accessibles.get(sig);
-        if (ams == null) {
-            return null;
-        }
-        for (Method am : ams) {
-            if (am.getReturnType() == m.getReturnType()) {
-                return am;
-            }
-        }
-        return null;
-    }
-
-    private static Method getFirstAccessibleMethod(MethodSignature sig, 
Map<MethodSignature, List<Method>> accessibles) {
-        List<Method> ams = accessibles.get(sig);
-        if (ams == null || ams.isEmpty()) {
-            return null;
-        }
-        return ams.get(0);
-    }
-
-    /**
-     * As of this writing, this is only used for testing if method order 
really doesn't mater.
-     */
-    private MethodDescriptor[] sortMethodDescriptors(MethodDescriptor[] 
methodDescriptors) {
-        return methodSorter != null ? 
methodSorter.sortMethodDescriptors(methodDescriptors) : methodDescriptors;
-    }
-
-    boolean isAllowedToExpose(Method method) {
-        return exposureLevel < BeansWrapper.EXPOSE_SAFE || 
!UnsafeMethods.isUnsafeMethod(method);
-    }
-
-    private static Map<Method, Class<?>[]> getArgTypesByMethod(Map<Object, 
Object> classInfo) {
-        @SuppressWarnings("unchecked")
-        Map<Method, Class<?>[]> argTypes = (Map<Method, Class<?>[]>) 
classInfo.get(ARG_TYPES_BY_METHOD_KEY);
-        if (argTypes == null) {
-            argTypes = new HashMap<>();
-            classInfo.put(ARG_TYPES_BY_METHOD_KEY, argTypes);
-        }
-        return argTypes;
-    }
-
-    private static final class MethodSignature {
-        private static final MethodSignature GET_STRING_SIGNATURE =
-                new MethodSignature("get", new Class[] { String.class });
-        private static final MethodSignature GET_OBJECT_SIGNATURE =
-                new MethodSignature("get", new Class[] { Object.class });
-
-        private final String name;
-        private final Class<?>[] args;
-
-        private MethodSignature(String name, Class<?>[] args) {
-            this.name = name;
-            this.args = args;
-        }
-
-        MethodSignature(Method method) {
-            this(method.getName(), method.getParameterTypes());
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (o instanceof MethodSignature) {
-                MethodSignature ms = (MethodSignature) o;
-                return ms.name.equals(name) && Arrays.equals(args, ms.args);
-            }
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            return name.hashCode() ^ args.length; // TODO That's a poor 
quality hash... isn't this a problem?
-        }
-    }
-
-    // 
-----------------------------------------------------------------------------------------------------------------
-    // Cache management:
-
-    /**
-     * Corresponds to {@link BeansWrapper#clearClassIntrospecitonCache()}.
-     * 
-     * @since 2.3.20
-     */
-    void clearCache() {
-        if (getHasSharedInstanceRestrictons()) {
-            throw new IllegalStateException(
-                    "It's not allowed to clear the whole cache in a read-only 
" + getClass().getName() +
-                            "instance. Use 
removeFromClassIntrospectionCache(String prefix) instead.");
-        }
-        forcedClearCache();
-    }
-
-    private void forcedClearCache() {
-        synchronized (sharedLock) {
-            cache.clear();
-            cacheClassNames.clear();
-            clearingCounter++;
-
-            for (WeakReference<Object> regedMfREf : modelFactories) {
-                Object regedMf = regedMfREf.get();
-                if (regedMf != null) {
-                    if (regedMf instanceof ClassBasedModelFactory) {
-                        ((ClassBasedModelFactory) regedMf).clearCache();
-                    } else if (regedMf instanceof ModelCache) {
-                        ((ModelCache) regedMf).clearCache();
-                    } else {
-                        throw new BugException();
-                    }
-                }
-            }
-
-            removeClearedModelFactoryReferences();
-        }
-    }
-
-    /**
-     * Corresponds to {@link 
BeansWrapper#removeFromClassIntrospectionCache(Class)}.
-     * 
-     * @since 2.3.20
-     */
-    void remove(Class<?> clazz) {
-        synchronized (sharedLock) {
-            cache.remove(clazz);
-            cacheClassNames.remove(clazz.getName());
-            clearingCounter++;
-
-            for (WeakReference<Object> regedMfREf : modelFactories) {
-                Object regedMf = regedMfREf.get();
-                if (regedMf != null) {
-                    if (regedMf instanceof ClassBasedModelFactory) {
-                        ((ClassBasedModelFactory) 
regedMf).removeFromCache(clazz);
-                    } else if (regedMf instanceof ModelCache) {
-                        ((ModelCache) regedMf).clearCache(); // doesn't 
support selective clearing ATM
-                    } else {
-                        throw new BugException();
-                    }
-                }
-            }
-
-            removeClearedModelFactoryReferences();
-        }
-    }
-
-    /**
-     * Returns the number of events so far that could make class introspection 
data returned earlier outdated.
-     */
-    int getClearingCounter() {
-        synchronized (sharedLock) {
-            return clearingCounter;
-        }
-    }
-
-    private void onSameNameClassesDetected(String className) {
-        // TODO: This behavior should be pluggable, as in environments where
-        // some classes are often reloaded or multiple versions of the
-        // same class is normal (OSGi), this will drop the cache contents
-        // too often.
-        LOG.info(
-                "Detected multiple classes with the same name, \"{}\". "
-                + "Assuming it was a class-reloading. Clearing class 
introspection caches to release old data.",
-                className);
-        forcedClearCache();
-    }
-
-    // 
-----------------------------------------------------------------------------------------------------------------
-    // Managing dependent objects:
-
-    void registerModelFactory(ClassBasedModelFactory mf) {
-        registerModelFactory((Object) mf);
-    }
-
-    void registerModelFactory(ModelCache mf) {
-        registerModelFactory((Object) mf);
-    }
-
-    private void registerModelFactory(Object mf) {
-        // Note that this `synchronized (sharedLock)` is also need for the 
BeansWrapper constructor to work safely.
-        synchronized (sharedLock) {
-            modelFactories.add(new WeakReference<>(mf, 
modelFactoriesRefQueue));
-            removeClearedModelFactoryReferences();
-        }
-    }
-
-    void unregisterModelFactory(ClassBasedModelFactory mf) {
-        unregisterModelFactory((Object) mf);
-    }
-
-    void unregisterModelFactory(ModelCache mf) {
-        unregisterModelFactory((Object) mf);
-    }
-
-    void unregisterModelFactory(Object mf) {
-        synchronized (sharedLock) {
-            for (Iterator<WeakReference<Object>> it = 
modelFactories.iterator(); it.hasNext(); ) {
-                Object regedMf = it.next().get();
-                if (regedMf == mf) {
-                    it.remove();
-                }
-            }
-
-        }
-    }
-
-    private void removeClearedModelFactoryReferences() {
-        Reference<?> cleardRef;
-        while ((cleardRef = modelFactoriesRefQueue.poll()) != null) {
-            synchronized (sharedLock) {
-                findClearedRef: for (Iterator<WeakReference<Object>> it = 
modelFactories.iterator(); it.hasNext(); ) {
-                    if (it.next() == cleardRef) {
-                        it.remove();
-                        break findClearedRef;
-                    }
-                }
-            }
-        }
-    }
-
-    // 
-----------------------------------------------------------------------------------------------------------------
-    // Extracting from introspection info:
-
-    static Class<?>[] getArgTypes(Map<Object, Object> classInfo, Method 
method) {
-        @SuppressWarnings("unchecked")
-        Map<Method, Class<?>[]> argTypesByMethod = (Map<Method, Class<?>[]>) 
classInfo.get(ARG_TYPES_BY_METHOD_KEY);
-        return argTypesByMethod.get(method);
-    }
-
-    /**
-     * Returns the number of introspected methods/properties that should be 
available via the TemplateHashModel
-     * interface.
-     */
-    int keyCount(Class<?> clazz) {
-        Map<Object, Object> map = get(clazz);
-        int count = map.size();
-        if (map.containsKey(CONSTRUCTORS_KEY)) count--;
-        if (map.containsKey(GENERIC_GET_KEY)) count--;
-        if (map.containsKey(ARG_TYPES_BY_METHOD_KEY)) count--;
-        return count;
-    }
-
-    /**
-     * Returns the Set of names of introspected methods/properties that should 
be available via the TemplateHashModel
-     * interface.
-     */
-    Set<Object> keySet(Class<?> clazz) {
-        Set<Object> set = new HashSet<>(get(clazz).keySet());
-        set.remove(CONSTRUCTORS_KEY);
-        set.remove(GENERIC_GET_KEY);
-        set.remove(ARG_TYPES_BY_METHOD_KEY);
-        return set;
-    }
-
-    // 
-----------------------------------------------------------------------------------------------------------------
-    // Properties
-
-    int getExposureLevel() {
-        return exposureLevel;
-    }
-
-    boolean getExposeFields() {
-        return exposeFields;
-    }
-
-    MethodAppearanceFineTuner getMethodAppearanceFineTuner() {
-        return methodAppearanceFineTuner;
-    }
-
-    MethodSorter getMethodSorter() {
-        return methodSorter;
-    }
-
-    /**
-     * Returns {@code true} if this instance was created with {@link 
ClassIntrospectorBuilder}, even if it wasn't
-     * actually put into the cache (as we reserve the right to do so in later 
versions).
-     */
-    boolean getHasSharedInstanceRestrictons() {
-        return hasSharedInstanceRestrictons;
-    }
-
-    /**
-     * Tells if this instance is (potentially) shared among {@link 
BeansWrapper} instances.
-     * 
-     * @see #getHasSharedInstanceRestrictons()
-     */
-    boolean isShared() {
-        return shared;
-    }
-
-    /**
-     * Almost always, you want to use {@link 
BeansWrapper#getSharedIntrospectionLock()}, not this! The only exception is
-     * when you get this to set the field returned by {@link 
BeansWrapper#getSharedIntrospectionLock()}.
-     */
-    Object getSharedLock() {
-        return sharedLock;
-    }
-
-    // 
-----------------------------------------------------------------------------------------------------------------
-    // Monitoring:
-
-    /** For unit testing only */
-    Object[] getRegisteredModelFactoriesSnapshot() {
-        synchronized (sharedLock) {
-            return modelFactories.toArray();
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/ClassIntrospectorBuilder.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/ClassIntrospectorBuilder.java
 
b/src/main/java/org/apache/freemarker/core/model/impl/beans/ClassIntrospectorBuilder.java
deleted file mode 100644
index c6f6cb6..0000000
--- 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/ClassIntrospectorBuilder.java
+++ /dev/null
@@ -1,190 +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.model.impl.beans;
-
-import java.lang.ref.Reference;
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.WeakReference;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-import org.apache.freemarker.core.Version;
-import org.apache.freemarker.core.util._NullArgumentException;
-
-final class ClassIntrospectorBuilder implements Cloneable {
-
-    private static final Map/*<PropertyAssignments, 
Reference<ClassIntrospector>>*/ INSTANCE_CACHE = new HashMap();
-    private static final ReferenceQueue INSTANCE_CACHE_REF_QUEUE = new 
ReferenceQueue(); 
-    
-    // Properties and their *defaults*:
-    private int exposureLevel = BeansWrapper.EXPOSE_SAFE;
-    private boolean exposeFields;
-    private MethodAppearanceFineTuner methodAppearanceFineTuner;
-    private MethodSorter methodSorter;
-    // Attention:
-    // - This is also used as a cache key, so non-normalized field values 
should be avoided.
-    // - If some field has a default value, it must be set until the end of 
the constructor. No field that has a
-    //   default can be left unset (like null).
-    // - If you add a new field, review all methods in this class, also the 
ClassIntrospector constructor
-    
-    ClassIntrospectorBuilder(ClassIntrospector ci) {
-        exposureLevel = ci.exposureLevel;
-        exposeFields = ci.exposeFields;
-        methodAppearanceFineTuner = ci.methodAppearanceFineTuner;
-        methodSorter = ci.methodSorter; 
-    }
-    
-    ClassIntrospectorBuilder(Version incompatibleImprovements) {
-        // Warning: incompatibleImprovements must not affect this object at 
versions increments where there's no
-        // change in the BeansWrapper.normalizeIncompatibleImprovements 
results. That is, this class may don't react
-        // to some version changes that affects BeansWrapper, but not the 
other way around.
-        _NullArgumentException.check(incompatibleImprovements);
-        // Currently nothing depends on incompatibleImprovements
-    }
-    
-    @Override
-    protected Object clone() {
-        try {
-            return super.clone();
-        } catch (CloneNotSupportedException e) {
-            throw new RuntimeException("Failed to clone 
ClassIntrospectorBuilder", e);
-        }
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + (exposeFields ? 1231 : 1237);
-        result = prime * result + exposureLevel;
-        result = prime * result + 
System.identityHashCode(methodAppearanceFineTuner);
-        result = prime * result + System.identityHashCode(methodSorter);
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) return true;
-        if (obj == null) return false;
-        if (getClass() != obj.getClass()) return false;
-        ClassIntrospectorBuilder other = (ClassIntrospectorBuilder) obj;
-        
-        if (exposeFields != other.exposeFields) return false;
-        if (exposureLevel != other.exposureLevel) return false;
-        if (methodAppearanceFineTuner != other.methodAppearanceFineTuner) 
return false;
-        return methodSorter == other.methodSorter;
-    }
-    
-    public int getExposureLevel() {
-        return exposureLevel;
-    }
-
-    /** See {@link BeansWrapper#setExposureLevel(int)}. */
-    public void setExposureLevel(int exposureLevel) {
-        if (exposureLevel < BeansWrapper.EXPOSE_ALL || exposureLevel > 
BeansWrapper.EXPOSE_NOTHING) {
-            throw new IllegalArgumentException("Illegal exposure level: " + 
exposureLevel);
-        }
-        
-        this.exposureLevel = exposureLevel;
-    }
-
-    public boolean getExposeFields() {
-        return exposeFields;
-    }
-
-    /** See {@link BeansWrapper#setExposeFields(boolean)}. */
-    public void setExposeFields(boolean exposeFields) {
-        this.exposeFields = exposeFields;
-    }
-
-    public MethodAppearanceFineTuner getMethodAppearanceFineTuner() {
-        return methodAppearanceFineTuner;
-    }
-
-    public void setMethodAppearanceFineTuner(MethodAppearanceFineTuner 
methodAppearanceFineTuner) {
-        this.methodAppearanceFineTuner = methodAppearanceFineTuner;
-    }
-
-    public MethodSorter getMethodSorter() {
-        return methodSorter;
-    }
-
-    public void setMethodSorter(MethodSorter methodSorter) {
-        this.methodSorter = methodSorter;
-    }
-
-    private static void removeClearedReferencesFromInstanceCache() {
-        Reference clearedRef;
-        while ((clearedRef = INSTANCE_CACHE_REF_QUEUE.poll()) != null) {
-            synchronized (INSTANCE_CACHE) {
-                findClearedRef: for (Iterator it = 
INSTANCE_CACHE.values().iterator(); it.hasNext(); ) {
-                    if (it.next() == clearedRef) {
-                        it.remove();
-                        break findClearedRef;
-                    }
-                }
-            }
-        }
-    }
-
-    /** For unit testing only */
-    static void clearInstanceCache() {
-        synchronized (INSTANCE_CACHE) {
-            INSTANCE_CACHE.clear();
-        }
-    }
-    
-    /** For unit testing only */
-    static Map getInstanceCache() {
-        return INSTANCE_CACHE;
-    }
-
-    /**
-     * Returns an instance that is possibly shared (singleton). Note that this 
comes with its own "shared lock",
-     * since everyone who uses this object will have to lock with that common 
object.
-     */
-    ClassIntrospector build() {
-        if ((methodAppearanceFineTuner == null || methodAppearanceFineTuner 
instanceof SingletonCustomizer)
-                && (methodSorter == null || methodSorter instanceof 
SingletonCustomizer)) {
-            // Instance can be cached.
-            ClassIntrospector instance;
-            synchronized (INSTANCE_CACHE) {
-                Reference instanceRef = (Reference) INSTANCE_CACHE.get(this);
-                instance = instanceRef != null ? (ClassIntrospector) 
instanceRef.get() : null;
-                if (instance == null) {
-                    ClassIntrospectorBuilder thisClone = 
(ClassIntrospectorBuilder) clone();  // prevent any aliasing issues
-                    instance = new ClassIntrospector(thisClone, new Object(), 
true, true);
-                    INSTANCE_CACHE.put(thisClone, new WeakReference(instance, 
INSTANCE_CACHE_REF_QUEUE));
-                }
-            }
-            
-            removeClearedReferencesFromInstanceCache();
-            
-            return instance;
-        } else {
-            // If methodAppearanceFineTuner or methodSorter is specified and 
isn't marked as a singleton, the
-            // ClassIntrospector can't be shared/cached as those objects could 
contain a back-reference to the
-            // BeansWrapper.
-            return new ClassIntrospector(this, new Object(), true, false);
-        }
-    }
-    
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/CollectionAdapter.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/CollectionAdapter.java
 
b/src/main/java/org/apache/freemarker/core/model/impl/beans/CollectionAdapter.java
deleted file mode 100644
index 74db4cb..0000000
--- 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/CollectionAdapter.java
+++ /dev/null
@@ -1,88 +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.model.impl.beans;
-
-import java.util.AbstractCollection;
-import java.util.Collection;
-import java.util.Iterator;
-
-import org.apache.freemarker.core.model.TemplateCollectionModel;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateModelAdapter;
-import org.apache.freemarker.core.model.TemplateModelException;
-import org.apache.freemarker.core.model.TemplateModelIterator;
-import org.apache.freemarker.core.util.UndeclaredThrowableException;
-
-/**
- * Adapts a {@link TemplateCollectionModel} to  {@link Collection}.
- */
-class CollectionAdapter extends AbstractCollection implements 
TemplateModelAdapter {
-    private final BeansWrapper wrapper;
-    private final TemplateCollectionModel model;
-    
-    CollectionAdapter(TemplateCollectionModel model, BeansWrapper wrapper) {
-        this.model = model;
-        this.wrapper = wrapper;
-    }
-    
-    @Override
-    public TemplateModel getTemplateModel() {
-        return model;
-    }
-    
-    @Override
-    public int size() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public Iterator iterator() {
-        try {
-            return new Iterator() {
-                final TemplateModelIterator i = model.iterator();
-    
-                @Override
-                public boolean hasNext() {
-                    try {
-                        return i.hasNext();
-                    } catch (TemplateModelException e) {
-                        throw new UndeclaredThrowableException(e);
-                    }
-                }
-                
-                @Override
-                public Object next() {
-                    try {
-                        return wrapper.unwrap(i.next());
-                    } catch (TemplateModelException e) {
-                        throw new UndeclaredThrowableException(e);
-                    }
-                }
-                
-                @Override
-                public void remove() {
-                    throw new UnsupportedOperationException();
-                }
-            };
-        } catch (TemplateModelException e) {
-            throw new UndeclaredThrowableException(e);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/CollectionModel.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/CollectionModel.java
 
b/src/main/java/org/apache/freemarker/core/model/impl/beans/CollectionModel.java
deleted file mode 100644
index d27a56d..0000000
--- 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/CollectionModel.java
+++ /dev/null
@@ -1,109 +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.model.impl.beans;
-
-import java.util.Collection;
-import java.util.List;
-
-import org.apache.freemarker.core.model.ObjectWrapper;
-import org.apache.freemarker.core.model.TemplateCollectionModel;
-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.TemplateSequenceModel;
-
-/**
- * <p>A special case of {@link BeanModel} that can wrap Java collections
- * and that implements the {@link TemplateCollectionModel} in order to be 
usable 
- * in a <tt>&lt;#list&gt;</tt> block.</p>
- */
-public class CollectionModel
-extends
-    StringModel
-implements
-    TemplateCollectionModel,
-    TemplateSequenceModel {
-    static final ModelFactory FACTORY =
-        new ModelFactory()
-        {
-            @Override
-            public TemplateModel create(Object object, ObjectWrapper wrapper) {
-                return new CollectionModel((Collection) object, (BeansWrapper) 
wrapper);
-            }
-        };
-
-
-    /**
-     * Creates a new model that wraps the specified collection object.
-     * @param collection the collection object to wrap into a model.
-     * @param wrapper the {@link BeansWrapper} associated with this model.
-     * Every model has to have an associated {@link BeansWrapper} instance. The
-     * model gains many attributes from its wrapper, including the caching 
-     * behavior, method exposure level, method-over-item shadowing policy etc.
-     */
-    public CollectionModel(Collection collection, BeansWrapper wrapper) {
-        super(collection, wrapper);
-    }
-
-    /**
-     * Retrieves the i-th object from the collection, wrapped as a 
TemplateModel.
-     * @throws TemplateModelException if the index is out of bounds, or the
-     * underlying collection is not a List.
-     */
-    @Override
-    public TemplateModel get(int index)
-    throws TemplateModelException {
-        // Don't forget to keep getSupportsIndexedAccess in sync with this!
-        if (object instanceof List) {
-            try {
-                return wrap(((List) object).get(index));
-            } catch (IndexOutOfBoundsException e) {
-                return null;
-//                throw new TemplateModelException("Index out of bounds: " + 
index);
-            }
-        } else {
-            throw new TemplateModelException("Underlying collection is not a 
list, it's " + object.getClass().getName());
-        }
-    }
-    
-    /**
-     * Tells if {@link #get(int)} will always fail for this object.
-     * As this object implements {@link TemplateSequenceModel},
-     * {@link #get(int)} should always work, but due to a design flaw, for
-     * non-{@link List} wrapped objects {@link #get(int)} will always fail.
-     * This method exists to ease working this problem around.
-     * 
-     * @since 2.3.17 
-     */
-    public boolean getSupportsIndexedAccess() {
-        return object instanceof List;
-    }
-    
-    @Override
-    public TemplateModelIterator iterator() {
-        return new IteratorModel(((Collection) object).iterator(), wrapper);
-    }
-
-    @Override
-    public int size() {
-        return ((Collection) object).size();
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/DateModel.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/DateModel.java 
b/src/main/java/org/apache/freemarker/core/model/impl/beans/DateModel.java
deleted file mode 100644
index 55419cd..0000000
--- a/src/main/java/org/apache/freemarker/core/model/impl/beans/DateModel.java
+++ /dev/null
@@ -1,79 +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.model.impl.beans;
-
-import java.util.Date;
-
-import org.apache.freemarker.core.model.ObjectWrapper;
-import org.apache.freemarker.core.model.TemplateDateModel;
-import org.apache.freemarker.core.model.TemplateModel;
-
-/**
- * Wraps arbitrary subclass of {@link java.util.Date} into a reflective model.
- * Beside acting as a {@link TemplateDateModel}, you can call all Java methods
- * on these objects as well.
- */
-public class DateModel
-extends
-    BeanModel
-implements
-    TemplateDateModel {
-    static final ModelFactory FACTORY =
-        new ModelFactory()
-        {
-            @Override
-            public TemplateModel create(Object object, ObjectWrapper wrapper) {
-                return new DateModel((Date) object, (BeansWrapper) wrapper);
-            }
-        };
-
-    private final int type;
-    
-    /**
-     * Creates a new model that wraps the specified date object.
-     * @param date the date object to wrap into a model.
-     * @param wrapper the {@link BeansWrapper} associated with this model.
-     * Every model has to have an associated {@link BeansWrapper} instance. The
-     * model gains many attributes from its wrapper, including the caching 
-     * behavior, method exposure level, method-over-item shadowing policy etc.
-     */
-    public DateModel(Date date, BeansWrapper wrapper) {
-        super(date, wrapper);
-        if (date instanceof java.sql.Date) {
-            type = DATE;
-        } else if (date instanceof java.sql.Time) {
-            type = TIME;
-        } else if (date instanceof java.sql.Timestamp) {
-            type = DATETIME;
-        } else {
-            type = wrapper.getDefaultDateType();
-        }
-    }
-
-    @Override
-    public Date getAsDate() {
-        return (Date) object;
-    }
-
-    @Override
-    public int getDateType() {
-        return type;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/EmptyCallableMemberDescriptor.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/EmptyCallableMemberDescriptor.java
 
b/src/main/java/org/apache/freemarker/core/model/impl/beans/EmptyCallableMemberDescriptor.java
deleted file mode 100644
index d0e6b8e..0000000
--- 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/EmptyCallableMemberDescriptor.java
+++ /dev/null
@@ -1,35 +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.model.impl.beans;
-
-/**
- * Represents that no member was chosen. Why it wasn't is represented by the 
two singleton instances,
- * {@link #NO_SUCH_METHOD} and {@link #AMBIGUOUS_METHOD}. (Note that instances 
of these are cached associated with the
- * argument types, thus it shouldn't store details that are specific to the 
actual argument values. In fact, it better
- * remains a set of singletons.)     
- */
-final class EmptyCallableMemberDescriptor extends 
MaybeEmptyCallableMemberDescriptor {
-    
-    static final EmptyCallableMemberDescriptor NO_SUCH_METHOD = new 
EmptyCallableMemberDescriptor();
-    static final EmptyCallableMemberDescriptor AMBIGUOUS_METHOD = new 
EmptyCallableMemberDescriptor();
-    
-    private EmptyCallableMemberDescriptor() { }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/EmptyMemberAndArguments.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/EmptyMemberAndArguments.java
 
b/src/main/java/org/apache/freemarker/core/model/impl/beans/EmptyMemberAndArguments.java
deleted file mode 100644
index 2e078c9..0000000
--- 
a/src/main/java/org/apache/freemarker/core/model/impl/beans/EmptyMemberAndArguments.java
+++ /dev/null
@@ -1,93 +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.model.impl.beans;
-
-import org.apache.freemarker.core._DelayedOrdinal;
-
-/**
- * Describes a failed member lookup. Instances of this must not be cached as 
instances may store the actual argument
- * values.
- */
-final class EmptyMemberAndArguments extends MaybeEmptyMemberAndArguments {
-    
-    static final EmptyMemberAndArguments WRONG_NUMBER_OF_ARGUMENTS
-            = new EmptyMemberAndArguments(
-                    "No compatible overloaded variation was found; wrong 
number of arguments.", true, null);
-    
-    private final Object errorDescription;
-    private final boolean numberOfArgumentsWrong;
-    private final Object[] unwrappedArguments;
-    
-    private EmptyMemberAndArguments(
-            Object errorDescription, boolean numberOfArgumentsWrong, Object[] 
unwrappedArguments) {
-        this.errorDescription = errorDescription;
-        this.numberOfArgumentsWrong = numberOfArgumentsWrong;
-        this.unwrappedArguments = unwrappedArguments;
-    }
-
-    static EmptyMemberAndArguments noCompatibleOverload(int unwrappableIndex) {
-        return new EmptyMemberAndArguments(
-                new Object[] { "No compatible overloaded variation was found; 
can't convert (unwrap) the ",
-                new _DelayedOrdinal(Integer.valueOf(unwrappableIndex)), " 
argument to the desired Java type." },
-                false,
-                null);
-    }
-    
-    static EmptyMemberAndArguments noCompatibleOverload(Object[] 
unwrappedArgs) {
-        return new EmptyMemberAndArguments(
-                "No compatible overloaded variation was found; declared 
parameter types and argument value types mismatch.",
-                false,
-                unwrappedArgs);
-    }
-
-    static EmptyMemberAndArguments ambiguous(Object[] unwrappedArgs) {
-        return new EmptyMemberAndArguments(
-                "Multiple compatible overloaded variations were found with the 
same priority.",
-                false,
-                unwrappedArgs);
-    }
-
-    static MaybeEmptyMemberAndArguments from(
-            EmptyCallableMemberDescriptor emtpyMemberDesc, Object[] 
unwrappedArgs) {
-        if (emtpyMemberDesc == EmptyCallableMemberDescriptor.NO_SUCH_METHOD) {
-            return noCompatibleOverload(unwrappedArgs);
-        } else if (emtpyMemberDesc == 
EmptyCallableMemberDescriptor.AMBIGUOUS_METHOD) {
-            return ambiguous(unwrappedArgs);
-        } else {
-            throw new IllegalArgumentException("Unrecognized constant: " + 
emtpyMemberDesc);
-        }
-    }
-
-    Object getErrorDescription() {
-        return errorDescription;
-    }
-
-    /**
-     * @return {@code null} if the error has occurred earlier than the full 
argument list was unwrapped.
-     */
-    Object[] getUnwrappedArguments() {
-        return unwrappedArguments;
-    }
-
-    public boolean isNumberOfArgumentsWrong() {
-        return numberOfArgumentsWrong;
-    }
-    
-}

Reply via email to