You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mc...@apache.org on 2011/10/16 09:30:57 UTC

svn commit: r1184772 - in /commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl: OgnlRuntime.java internal/ConcurrentClassCache.java internal/ConcurrentHashMapCache.java

Author: mcucchiara
Date: Sun Oct 16 07:30:57 2011
New Revision: 1184772

URL: http://svn.apache.org/viewvc?rev=1184772&view=rev
Log:
Added abstraction layer

Added:
    commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ConcurrentHashMapCache.java
Modified:
    commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/OgnlRuntime.java
    commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ConcurrentClassCache.java

Modified: commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/OgnlRuntime.java
URL: http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/OgnlRuntime.java?rev=1184772&r1=1184771&r2=1184772&view=diff
==============================================================================
--- commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/OgnlRuntime.java (original)
+++ commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/OgnlRuntime.java Sun Oct 16 07:30:57 2011
@@ -23,12 +23,17 @@ package org.apache.commons.ognl;
 
 import org.apache.commons.ognl.enhance.ExpressionCompiler;
 import org.apache.commons.ognl.enhance.OgnlExpressionCompiler;
-import org.apache.commons.ognl.internal.CacheEntryFactory;
-import org.apache.commons.ognl.internal.CacheException;
 import org.apache.commons.ognl.internal.ClassCache;
-import org.apache.commons.ognl.internal.ClassCacheEntryFactory;
 import org.apache.commons.ognl.internal.ClassCacheHandler;
 import org.apache.commons.ognl.internal.ConcurrentClassCache;
+import org.apache.commons.ognl.internal.ConcurrentHashMapCache;
+import org.apache.commons.ognl.internal.entry.FiedlCacheCacheEntryFactory;
+import org.apache.commons.ognl.internal.entry.ConstructorCacheEntryFactory;
+import org.apache.commons.ognl.internal.entry.DeclaredMethodCacheEntry;
+import org.apache.commons.ognl.internal.entry.DeclaredMethodCacheEntryFactory;
+import org.apache.commons.ognl.internal.entry.PermissionCacheEntry;
+import org.apache.commons.ognl.internal.entry.PermissionCacheEntryFactory;
+import org.apache.commons.ognl.internal.entry.PropertyDescriptorCacheEntryFactory;
 
 import java.beans.BeanInfo;
 import java.beans.IndexedPropertyDescriptor;
@@ -156,20 +161,19 @@ public class OgnlRuntime
     static final ClassCache<NullHandler> _nullHandlers = new ConcurrentClassCache<NullHandler>( );
 
     static final ClassCache<Map<String, PropertyDescriptor>> _propertyDescriptorCache =
-        new ConcurrentClassCache<Map<String, PropertyDescriptor>>( );
+        new ConcurrentClassCache<Map<String, PropertyDescriptor>>(new PropertyDescriptorCacheEntryFactory());
 
-    static final ClassCache<List<Constructor<?>>> _constructorCache = new ConcurrentClassCache<List<Constructor<?>>>( );
+    static final ClassCache<List<Constructor<?>>> _constructorCache = new ConcurrentClassCache<List<Constructor<?>>>(new ConstructorCacheEntryFactory() );
 
-    static final ClassCache<Map<String, List<Method>>> _staticMethodCache = new ConcurrentClassCache<Map<String, List<Method>>>( );
+    static final ConcurrentHashMapCache<DeclaredMethodCacheEntry, Map<String, List<Method>>> _methodCache =
+        new ConcurrentHashMapCache<DeclaredMethodCacheEntry, Map<String, List<Method>>>(
+            new DeclaredMethodCacheEntryFactory( ) );
 
-    static final ClassCache<Map<String, List<Method>>> _instanceMethodCache = new ConcurrentClassCache<Map<String, List<Method>>>( );
+    static final ConcurrentHashMapCache<PermissionCacheEntry, Permission> _invokePermissionCache =
+        new ConcurrentHashMapCache<PermissionCacheEntry, Permission>( new PermissionCacheEntryFactory( ) );
 
-    static final ClassCache<Map<String, Permission>> _invokePermissionCache = new ConcurrentClassCache<Map<String, Permission>>( );
-
-    static final ClassCache<Map<String, Field>> _fieldCache = new ConcurrentClassCache<Map<String, Field>>( );
-
-    static final ClassCache[] _declaredMethods =
-        new ClassCache[]{ new ConcurrentClassCache( ), new ConcurrentClassCache( ) };
+    static final ClassCache<Map<String, Field>> _fieldCache =
+        new ConcurrentClassCache<Map<String, Field>>( new FiedlCacheCacheEntryFactory( ) );
 
     static final Map<String, Class<?>> _primitiveTypes = new HashMap<String, Class<?>>( 101 );
 
@@ -413,12 +417,11 @@ public class OgnlRuntime
         _ctorParameterTypesCache.clear( );
         _propertyDescriptorCache.clear( );
         _constructorCache.clear( );
-        _staticMethodCache.clear( );
-        _instanceMethodCache.clear( );
+        _methodCache.clear( );
         _invokePermissionCache.clear( );
         _fieldCache.clear( );
-        _declaredMethods[0].clear( );
-        _declaredMethods[1].clear( );
+//        _setterMethods.clear( );
+//        _getterMethods.clear( );
         _methodAccessCache.clear( );
     }
 
@@ -819,31 +822,7 @@ public class OgnlRuntime
     public static Permission getPermission( final Method method )
         throws OgnlException
     {
-        final Class<?> mc = method.getDeclaringClass( );
-
-        CacheEntryFactory<Class<?>, Map<String, Permission>> cacheEntryFactory =
-            new CacheEntryFactory<Class<?>, Map<String, Permission>>( )
-            {
-                public Map<String, Permission> create( Class<?> key )
-                    throws CacheException
-                {
-                    Map<String, Permission> permissions = _invokePermissionCache.get( mc );
-                    if ( permissions == null )
-                    {
-                        _invokePermissionCache.put( mc, permissions = new HashMap<String, Permission>( 101 ) );
-                    }
-                    Permission result = permissions.get( method.getName( ) );
-                    if ( result == null )
-                    {
-                        result = new OgnlInvokePermission( "invoke." + mc.getName( ) + "." + method.getName( ) );
-                        permissions.put( method.getName( ), result );
-                    }
-                    return permissions;
-                }
-            };
-        Map<String, Permission> permissions = _invokePermissionCache.get( mc, cacheEntryFactory );
-
-        return permissions.get( method.getName( ) );
+        return _invokePermissionCache.get( new PermissionCacheEntry( method ) );
     }
 
     public static Object invokeMethod( Object target, Method method, Object[] argsArray )
@@ -1673,60 +1652,29 @@ public class OgnlRuntime
     public static List<Constructor<?>> getConstructors( final Class<?> targetClass )
         throws OgnlException
     {
-        return _constructorCache.get( targetClass, new ClassCacheEntryFactory<List<Constructor<?>>>( )
-        {
-            public List<Constructor<?>> create( Class<?> key )
-                throws CacheException
-            {
-                return Arrays.asList( targetClass.getConstructors( ) );
-            }
-        } );
+        return _constructorCache.get( targetClass );
     }
 
-    public static Map<String, List<Method>> getMethods( final Class<?> targetClass, final boolean staticMethods )
+    /**
+     * @param targetClass
+     * @param staticMethods if true (false) returns only the (non-)static methods
+     * @return Returns the map of methods for a given class
+     * @throws OgnlException
+     */
+    public static Map<String, List<Method>> getMethods( Class<?> targetClass, boolean staticMethods )
         throws OgnlException
     {
-        CacheEntryFactory<Class<?>, Map<String, List<Method>>> entryFactory=new CacheEntryFactory<Class<?>, Map<String, List<Method>>>( )
+        DeclaredMethodCacheEntry.MethodType type;
+        if ( staticMethods )
         {
-            public Map<String, List<Method>> create( Class<?> key )
-                throws CacheException
-            {
-                Map<String, List<Method>> result = new HashMap<String, List<Method>>( 23 );
-
-                Class<?> c = key;
-                while ( c != null )
-                {
-                    Method[] ma = c.getDeclaredMethods( );
-
-                    for ( Method method : ma )
-                    {
-                        // skip over synthetic methods
-
-                        if ( !isMethodCallable( method ) )
-                        {
-                            continue;
-                        }
-
-                        if ( Modifier.isStatic( method.getModifiers( ) ) == staticMethods )
-                        {
-                            List<Method> ml = result.get( method.getName( ) );
-
-                            if ( ml == null )
-                            {
-                                result.put( method.getName( ), ml = new ArrayList<Method>( ) );
-                            }
-
-                            ml.add( method );
-                        }
-                    }
-                    c = c.getSuperclass( );
-                }
-                return result;
-            }
-        };
+            type = DeclaredMethodCacheEntry.MethodType.STATIC;
+        }
+        else
+        {
+            type = DeclaredMethodCacheEntry.MethodType.NON_STATIC;
 
-        ClassCache<Map<String, List<Method>>> cache = ( staticMethods ? _staticMethodCache : _instanceMethodCache );
-        return cache.get( targetClass, entryFactory );
+        }
+        return _methodCache.get( new DeclaredMethodCacheEntry( targetClass, type) );
     }
 
     public static List<Method> getMethods( Class<?> targetClass, String name, boolean staticMethods )
@@ -1738,21 +1686,7 @@ public class OgnlRuntime
     public static Map<String, Field> getFields( Class<?> targetClass )
         throws OgnlException
     {
-        CacheEntryFactory<Class<?>, Map<String, Field>> entryFactory=new CacheEntryFactory<Class<?>, Map<String, Field>>( )
-        {
-            public Map<String, Field> create( Class<?> key )
-                throws CacheException
-            {
-                Field[] declaredFields = key.getDeclaredFields( );
-                HashMap<String, Field> result = new HashMap<String, Field>( declaredFields.length);
-                for ( Field field : declaredFields )
-                {
-                    result.put( field.getName( ), field );
-                }
-                return result ;
-            }
-        };
-        return _fieldCache.get( targetClass, entryFactory );
+        return _fieldCache.get( targetClass );
     }
 
     public static Field getField( Class<?> inClass, String name )
@@ -1763,7 +1697,7 @@ public class OgnlRuntime
         if ( o == null )
         {
             // if o is null, it should search along the superclasses
-            Class<?> sc = inClass.getSuperclass();
+            Class<?> sc = inClass.getSuperclass( );
             while ( ( sc != null ) )
             {
                 o = getFields( sc ).get( name );
@@ -1941,68 +1875,39 @@ public class OgnlRuntime
         throw new OgnlException( "Could not get static field " + fieldName + " from class " + className, reason );
     }
 
-    public static List<Method> getDeclaredMethods( Class<?> targetClass, String propertyName, boolean findSets )
+    /**
+     *
+     * @param targetClass
+     * @param propertyName
+     * @param findSets
+     * @return Returns the list of (g)setter of a class for a given property name
+     * @throws OgnlException
+     */
+    public static List<Method> getDeclaredMethods( final Class<?> targetClass, final String propertyName,
+                                                   final boolean findSets )
         throws OgnlException
     {
-        List<Method> result = null;
-        ClassCache cache = _declaredMethods[findSets ? 0 : 1];
-
-        synchronized ( cache )
+        String baseName = Character.toUpperCase( propertyName.charAt( 0 ) ) + propertyName.substring( 1 );
+        List<Method> result = new ArrayList<Method>( );
+        List<String> find = new ArrayList<String>( 2 );
+        if(findSets)
         {
-            Map<String, List<Method>> propertyCache = (Map<String, List<Method>>) cache.get( targetClass );
-
-            if ( ( propertyCache == null ) || ( ( result = propertyCache.get( propertyName ) ) == null ) )
-            {
-
-                String baseName = Character.toUpperCase( propertyName.charAt( 0 ) ) + propertyName.substring( 1 );
-
-                for ( Class<?> c = targetClass; c != null; c = c.getSuperclass( ) )
-                {
-                    Method[] methods = c.getDeclaredMethods( );
-
-                    for ( Method method : methods )
-                    {
-
-                        if ( !isMethodCallable( method ) )
-                        {
-                            continue;
-                        }
-
-                        String ms = method.getName( );
-
-                        if ( ms.endsWith( baseName ) )
-                        {
-                            boolean isSet, isIs = false;
-
-                            if ( ( isSet = ms.startsWith( SET_PREFIX ) ) || ms.startsWith( GET_PREFIX ) || ( isIs =
-                                ms.startsWith( IS_PREFIX ) ) )
-                            {
-                                int prefixLength = ( isIs ? 2 : 3 );
-
-                                if ( isSet == findSets )
-                                {
-                                    if ( baseName.length( ) == ( ms.length( ) - prefixLength ) )
-                                    {
-                                        if ( result == null )
-                                        {
-                                            result = new ArrayList<Method>( );
-                                        }
-                                        result.add( method );
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-                if ( propertyCache == null )
-                {
-                    cache.put( targetClass, propertyCache = new HashMap<String, List<Method>>( 101 ) );
-                }
-
-                propertyCache.put( propertyName, result );
-            }
-            return result;
+            find.add( SET_PREFIX + baseName);
+        } else
+        {
+            find.add( IS_PREFIX + baseName );
+            find.add(GET_PREFIX + baseName );
+            
         }
+        for ( String s : find )
+        {
+            List<Method> methodList = _methodCache.get( new DeclaredMethodCacheEntry( targetClass ) ).get( s );
+            if(methodList!=null)
+                result.addAll( methodList );
+        }
+
+        return result;
+            
     }
 
     /**
@@ -2011,7 +1916,8 @@ public class OgnlRuntime
      * @param m The method to check.
      * @return True if the method should be callable, false otherwise.
      */
-    static boolean isMethodCallable( Method m )
+    //TODO: the method was intented as private, so it needs to move in a util class
+    public static boolean isMethodCallable( Method m )
     {
         return !( ( isJdk15( ) && m.isSynthetic( ) ) || Modifier.isVolatile( m.getModifiers( ) ) );
 
@@ -2146,7 +2052,8 @@ public class OgnlRuntime
         return result;
     }
 
-    static void findObjectIndexedPropertyDescriptors( Class<?> targetClass, Map<String, PropertyDescriptor> intoMap )
+    public static void findObjectIndexedPropertyDescriptors( Class<?> targetClass,
+                                                             Map<String, PropertyDescriptor> intoMap )
         throws OgnlException
     {
         Map<String, List<Method>> allMethods = getMethods( targetClass, false );
@@ -2243,50 +2150,7 @@ public class OgnlRuntime
     public static Map<String, PropertyDescriptor> getPropertyDescriptors( final Class<?> targetClass )
         throws IntrospectionException, OgnlException
     {
-        return _propertyDescriptorCache.get( targetClass, new ClassCacheEntryFactory<Map<String, PropertyDescriptor>>( )
-        {
-            public Map<String, PropertyDescriptor> create( Class<?> key )
-                throws CacheException
-            {
-                Map<String, PropertyDescriptor> result = new HashMap<String, PropertyDescriptor>( 101 );
-                PropertyDescriptor[] pda;
-                try
-                {
-                    pda = Introspector.getBeanInfo( targetClass ).getPropertyDescriptors( );
-
-                    for ( int i = 0, icount = pda.length; i < icount; i++ )
-                    {
-                        // workaround for Introspector bug 6528714 (bugs.sun.com)
-                        if ( pda[i].getReadMethod( ) != null && !isMethodCallable( pda[i].getReadMethod( ) ) )
-                        {
-                            pda[i].setReadMethod(
-                                findClosestMatchingMethod( targetClass, pda[i].getReadMethod( ), pda[i].getName( ),
-                                                           pda[i].getPropertyType( ), true ) );
-                        }
-                        if ( pda[i].getWriteMethod( ) != null && !isMethodCallable( pda[i].getWriteMethod( ) ) )
-                        {
-                            pda[i].setWriteMethod(
-                                findClosestMatchingMethod( targetClass, pda[i].getWriteMethod( ), pda[i].getName( ),
-                                                           pda[i].getPropertyType( ), false ) );
-                        }
-
-                        result.put( pda[i].getName( ), pda[i] );
-                    }
-
-                    findObjectIndexedPropertyDescriptors( targetClass, result );
-                    _propertyDescriptorCache.put( targetClass, result );
-                }
-                catch ( IntrospectionException e )
-                {
-                    throw new CacheException( e );
-                }
-                catch ( OgnlException e )
-                {
-                    throw new CacheException( e );
-                }
-                return result;
-            }
-        } );
+        return _propertyDescriptorCache.get( targetClass );
     }
 
     /**
@@ -2304,25 +2168,6 @@ public class OgnlRuntime
         return getPropertyDescriptors( targetClass ).get( propertyName );
     }
 
-    static Method findClosestMatchingMethod( Class<?> targetClass, Method m, String propertyName, Class<?> propertyType,
-                                             boolean isReadMethod )
-        throws OgnlException
-    {
-        List<Method> methods = getDeclaredMethods( targetClass, propertyName, !isReadMethod );
-
-        for ( Method method : methods )
-        {
-            if ( method.getName( ).equals( m.getName( ) ) && m.getReturnType( ).isAssignableFrom( m.getReturnType( ) )
-                && method.getReturnType( ) == propertyType
-                && method.getParameterTypes( ).length == m.getParameterTypes( ).length )
-            {
-                return method;
-            }
-        }
-
-        return m;
-    }
-
     public static PropertyDescriptor[] getPropertyDescriptorsArray( Class<?> targetClass )
         throws IntrospectionException, OgnlException
     {
@@ -2596,12 +2441,11 @@ public class OgnlRuntime
 
         _propertyDescriptorCache.setClassInspector( _cacheInspector );
         _constructorCache.setClassInspector( _cacheInspector );
-        _staticMethodCache.setClassInspector( _cacheInspector );
-        _instanceMethodCache.setClassInspector( _cacheInspector );
-        _invokePermissionCache.setClassInspector( _cacheInspector );
+//        _methodCache.setClassInspector( _cacheInspector );
+//        _invokePermissionCache.setClassInspector( _cacheInspector );
         _fieldCache.setClassInspector( _cacheInspector );
-        _declaredMethods[0].setClassInspector( _cacheInspector );
-        _declaredMethods[1].setClassInspector( _cacheInspector );
+//        _setterMethods.setClassInspector( _cacheInspector );
+//        _getterMethods.setClassInspector( _cacheInspector );
     }
 
     public static Method getMethod( OgnlContext context, Class<?> target, String name, Node[] children,

Modified: commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ConcurrentClassCache.java
URL: http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ConcurrentClassCache.java?rev=1184772&r1=1184771&r2=1184772&view=diff
==============================================================================
--- commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ConcurrentClassCache.java (original)
+++ commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ConcurrentClassCache.java Sun Oct 16 07:30:57 2011
@@ -22,64 +22,35 @@
 package org.apache.commons.ognl.internal;
 
 import org.apache.commons.ognl.ClassCacheInspector;
+import org.apache.commons.ognl.internal.entry.CacheEntryFactory;
 
-import java.util.concurrent.ConcurrentHashMap;
-
-public class ConcurrentClassCache<V>
-    implements ClassCache<V>
+public class ConcurrentClassCache<T>
+    extends ConcurrentHashMapCache<Class<?>,T>
+    implements ClassCache<T>
 {
     private ClassCacheInspector inspector;
 
-    private ConcurrentHashMap<Class<?>, V> cache = new ConcurrentHashMap<Class<?>, V>();
-
-    public ConcurrentClassCache()
-    {
-    }
-
-
-    public void setClassInspector( ClassCacheInspector inspector )
-    {
-        this.inspector = inspector;
-    }
-
-    public void clear()
+    public ConcurrentClassCache( )
     {
-        cache.clear();
     }
 
-    public int getSize()
+    public ConcurrentClassCache( CacheEntryFactory<Class<?>,T> entryFactory )
     {
-        return cache.size();
+        super( entryFactory );
     }
 
-    public V get( Class<?> key )
-        throws CacheException
-    {
-        return get( key, null );
-    }
-
-    public V get( Class<?> key, CacheEntryFactory<Class<?>, V> cacheEntryFactory )
-        throws CacheException
+    public void setClassInspector( ClassCacheInspector inspector )
     {
-        V v = cache.get( key );
-        if ( v == null && cacheEntryFactory != null )
-        {
-            return put( key, cacheEntryFactory.create( key ) );
-        }
-        return v;
+        this.inspector = inspector;
     }
 
-    public V put( Class<?> key, V value )
+    @Override
+    public T put( Class<?> key, T value )
     {
         if ( inspector != null && !inspector.shouldCache( key ) )
         {
             return value;
         }
-        V collision = cache.putIfAbsent( key, value );
-        if ( collision != null )
-        {
-            return collision;
-        }
-        return value;
+        return super.put( key, value );
     }
 }

Added: commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ConcurrentHashMapCache.java
URL: http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ConcurrentHashMapCache.java?rev=1184772&view=auto
==============================================================================
--- commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ConcurrentHashMapCache.java (added)
+++ commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ConcurrentHashMapCache.java Sun Oct 16 07:30:57 2011
@@ -0,0 +1,98 @@
+/*
+ * $Id: $
+ *
+ * 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.commons.ognl.internal;
+
+import org.apache.commons.ognl.internal.entry.CacheEntryFactory;
+import org.apache.commons.ognl.internal.entry.MatchingCacheEntryFactory;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+public class ConcurrentHashMapCache<K, V>
+    implements Cache<K, V>
+{
+    private ConcurrentHashMap<K, V> cache = new ConcurrentHashMap<K, V>( );
+
+    private CacheEntryFactory<K, V> cacheEntryFactory;
+
+    public ConcurrentHashMapCache( )
+    {
+    }
+
+    public ConcurrentHashMapCache( CacheEntryFactory<K, V> cacheEntryFactory )
+    {
+        this.cacheEntryFactory = cacheEntryFactory;
+    }
+
+    public void clear( )
+    {
+        cache.clear( );
+    }
+
+    public int getSize( )
+    {
+        return cache.size( );
+    }
+
+    public V get( K key)
+        throws CacheException
+    {
+        V v = cache.get( key );
+        if ( shouldCreate( cacheEntryFactory, v ) )
+        {
+            return put( key, cacheEntryFactory.create( key ) );
+        }
+        return v;
+    }
+
+    protected boolean shouldCreate( CacheEntryFactory<K, V> cacheEntryFactory, V v )
+        throws CacheException
+    {
+        if ( cacheEntryFactory != null )
+        {
+            if ( v == null )
+            {
+                return true;
+            }
+
+            if ( cacheEntryFactory instanceof MatchingCacheEntryFactory)
+            {
+                return !( (MatchingCacheEntryFactory<K,V>) cacheEntryFactory ).match( v );
+            }
+        }
+        return false;
+    }
+
+    public V put( K key, V value )
+    {
+        V collision = cache.putIfAbsent( key, value );
+        if ( collision != null )
+        {
+            return collision;
+        }
+        return value;
+    }
+
+    public boolean contains( K key)
+    {
+        return this.cache.contains( key );
+    }
+}