Author: mcucchiara Date: Sun Oct 16 21:27:18 2011 New Revision: 1184935 URL: http://svn.apache.org/viewvc?rev=1184935&view=rev Log: new GenericMethodParameterType cache implementation
Added: commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/entry/GenericMethodParameterTypeCacheEntry.java commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/entry/GenericMethodParameterTypeFactory.java commons/proper/ognl/branches/new-cache-approach/src/test/java/org/apache/commons/ognl/internal/GenericMethodParameterTypeCacheTest.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/test/java/org/apache/commons/ognl/TestOgnlRuntime.java commons/proper/ognl/branches/new-cache-approach/src/test/java/org/apache/commons/ognl/test/OgnlTestCase.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=1184935&r1=1184934&r2=1184935&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 21:27:18 2011 @@ -23,14 +23,18 @@ 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.Cache; +import org.apache.commons.ognl.internal.CacheException; import org.apache.commons.ognl.internal.ClassCache; 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.FiedlCacheEntryFactory; 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.FiedlCacheEntryFactory; +import org.apache.commons.ognl.internal.entry.GenericMethodParameterTypeCacheEntry; +import org.apache.commons.ognl.internal.entry.GenericMethodParameterTypeFactory; import org.apache.commons.ognl.internal.entry.PermissionCacheEntry; import org.apache.commons.ognl.internal.entry.PermissionCacheEntryFactory; import org.apache.commons.ognl.internal.entry.PropertyDescriptorCacheEntryFactory; @@ -41,10 +45,8 @@ import java.beans.IntrospectionException import java.beans.Introspector; import java.beans.MethodDescriptor; import java.beans.PropertyDescriptor; -import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; -import java.lang.reflect.GenericArrayType; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; import java.lang.reflect.Method; @@ -52,12 +54,10 @@ import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Proxy; import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; import java.math.BigDecimal; import java.math.BigInteger; import java.security.Permission; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; @@ -181,7 +181,7 @@ public class OgnlRuntime static final Map<Method, Class<?>[]> _methodParameterTypesCache = new HashMap<Method, Class<?>[]>( 101 ); - static final Map<Method, Class<?>[]> _genericMethodParameterTypesCache = new HashMap<Method, Class<?>[]>( 101 ); + static final Cache<GenericMethodParameterTypeCacheEntry, Class<?>[]> _genericMethodParameterTypesCache = new ConcurrentHashMapCache<GenericMethodParameterTypeCacheEntry, Class<?>[]>( new GenericMethodParameterTypeFactory( ) );; static final Map<Constructor<?>, Class<?>[]> _ctorParameterTypesCache = new HashMap<Constructor<?>, Class<?>[]>( 101 ); @@ -671,6 +671,7 @@ public class OgnlRuntime * @return Array of parameter types for the given method. */ public static Class<?>[] findParameterTypes( Class<?> type, Method m ) + throws CacheException { if ( type == null ) { @@ -683,87 +684,18 @@ public class OgnlRuntime return getParameterTypes( m ); } - synchronized ( _genericMethodParameterTypesCache ) - { - Class<?>[] types; - - if ( ( types = _genericMethodParameterTypesCache.get( m ) ) != null ) - { - ParameterizedType genericSuperclass = (ParameterizedType) type.getGenericSuperclass( ); - if ( Arrays.equals( types, genericSuperclass.getActualTypeArguments( ) ) ) - { - return types; - } - } - - ParameterizedType param = (ParameterizedType) type.getGenericSuperclass( ); - Type[] genTypes = m.getGenericParameterTypes( ); - TypeVariable<?>[] declaredTypes = m.getDeclaringClass( ).getTypeParameters( ); - - types = new Class[genTypes.length]; - - for ( int i = 0; i < genTypes.length; i++ ) - { - TypeVariable<?> paramType = null; - - if ( TypeVariable.class.isInstance( genTypes[i] ) ) - { - paramType = (TypeVariable<?>) genTypes[i]; - } - else if ( GenericArrayType.class.isInstance( genTypes[i] ) ) - { - paramType = (TypeVariable<?>) ( (GenericArrayType) genTypes[i] ).getGenericComponentType( ); - } - else if ( ParameterizedType.class.isInstance( genTypes[i] ) ) - { - types[i] = (Class<?>) ( (ParameterizedType) genTypes[i] ).getRawType( ); - continue; - } - else if ( Class.class.isInstance( genTypes[i] ) ) - { - types[i] = (Class<?>) genTypes[i]; - continue; - } - - Class<?> resolved = resolveType( param, paramType, declaredTypes ); - - if ( resolved != null ) - { - if ( GenericArrayType.class.isInstance( genTypes[i] ) ) - { - resolved = Array.newInstance( resolved, 0 ).getClass( ); - } - - types[i] = resolved; - continue; - } - - types[i] = m.getParameterTypes( )[i]; - } - - _genericMethodParameterTypesCache.put( m, types ); - - return types; - } - } - - static Class<?> resolveType( ParameterizedType param, TypeVariable<?> var, TypeVariable<?>[] declaredTypes ) - { - if ( param.getActualTypeArguments( ).length < 1 ) - { - return null; - } + Class<?>[] types = _genericMethodParameterTypesCache.get( new GenericMethodParameterTypeCacheEntry( m, type ) ); - for ( int i = 0; i < declaredTypes.length; i++ ) + /*if ( types != null ) { - if ( !TypeVariable.class.isInstance( param.getActualTypeArguments( )[i] ) - && declaredTypes[i].getName( ).equals( var.getName( ) ) ) + ParameterizedType genericSuperclass = (ParameterizedType) type.getGenericSuperclass( ); + if ( Arrays.equals( types, genericSuperclass.getActualTypeArguments( ) ) ) { - return (Class<?>) param.getActualTypeArguments( )[i]; + return types; } } - - return null; +*/ + return types; } static Class<?> findType( Type[] types, Class<?> type ) @@ -1916,7 +1848,7 @@ public class OgnlRuntime * @param m The method to check. * @return True if the method should be callable, false otherwise. */ - //TODO: the method was intented as private, so it needs to move in a util class + //TODO: the method was intented as private, so it'd need to move in a util class public static boolean isMethodCallable( Method m ) { return !( ( isJdk15( ) && m.isSynthetic( ) ) || Modifier.isVolatile( m.getModifiers( ) ) ); Added: commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/entry/GenericMethodParameterTypeCacheEntry.java URL: http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/entry/GenericMethodParameterTypeCacheEntry.java?rev=1184935&view=auto ============================================================================== --- commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/entry/GenericMethodParameterTypeCacheEntry.java (added) +++ commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/entry/GenericMethodParameterTypeCacheEntry.java Sun Oct 16 21:27:18 2011 @@ -0,0 +1,56 @@ +package org.apache.commons.ognl.internal.entry; + +import java.lang.reflect.Method; + +/** +* User: Maurizio Cucchiara +* Date: 10/16/11 +* Time: 9:28 PM +*/ +public class GenericMethodParameterTypeCacheEntry + implements CacheEntry +{ + Method method; + + Class<?> type; + + public GenericMethodParameterTypeCacheEntry( Method method, Class<?> type ) + { + this.method = method; + this.type = type; + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( !( o instanceof GenericMethodParameterTypeCacheEntry ) ) + { + return false; + } + + GenericMethodParameterTypeCacheEntry that = (GenericMethodParameterTypeCacheEntry) o; + + if ( !method.equals( that.method ) ) + { + return false; + } + if ( !type.equals( that.type ) ) + { + return false; + } + + return true; + } + + @Override + public int hashCode( ) + { + int result = method.hashCode( ); + result = 31 * result + type.hashCode( ); + return result; + } +} Added: commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/entry/GenericMethodParameterTypeFactory.java URL: http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/entry/GenericMethodParameterTypeFactory.java?rev=1184935&view=auto ============================================================================== --- commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/entry/GenericMethodParameterTypeFactory.java (added) +++ commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/entry/GenericMethodParameterTypeFactory.java Sun Oct 16 21:27:18 2011 @@ -0,0 +1,89 @@ +package org.apache.commons.ognl.internal.entry; + +import org.apache.commons.ognl.internal.CacheException; + +import java.lang.reflect.Array; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; + +/** +* User: Maurizio Cucchiara +* Date: 10/16/11 +* Time: 9:29 PM +*/ +public class GenericMethodParameterTypeFactory + implements CacheEntryFactory<GenericMethodParameterTypeCacheEntry, Class<?>[]> +{ + public Class<?>[] create( GenericMethodParameterTypeCacheEntry entry ) + throws CacheException + { + Class<?>[] types; + + ParameterizedType param = (ParameterizedType) entry.type.getGenericSuperclass( ); + Type[] genTypes = entry.method.getGenericParameterTypes( ); + TypeVariable<?>[] declaredTypes = entry.method.getDeclaringClass( ).getTypeParameters( ); + + types = new Class[genTypes.length]; + + for ( int i = 0; i < genTypes.length; i++ ) + { + TypeVariable<?> paramType = null; + + if ( TypeVariable.class.isInstance( genTypes[i] ) ) + { + paramType = (TypeVariable<?>) genTypes[i]; + } + else if ( GenericArrayType.class.isInstance( genTypes[i] ) ) + { + paramType = (TypeVariable<?>) ( (GenericArrayType) genTypes[i] ).getGenericComponentType( ); + } + else if ( ParameterizedType.class.isInstance( genTypes[i] ) ) + { + types[i] = (Class<?>) ( (ParameterizedType) genTypes[i] ).getRawType( ); + continue; + } + else if ( Class.class.isInstance( genTypes[i] ) ) + { + types[i] = (Class<?>) genTypes[i]; + continue; + } + + Class<?> resolved = resolveType( param, paramType, declaredTypes ); + + if ( resolved != null ) + { + if ( GenericArrayType.class.isInstance( genTypes[i] ) ) + { + resolved = Array.newInstance( resolved, 0 ).getClass( ); + } + + types[i] = resolved; + continue; + } + types[i] = entry.method.getParameterTypes( )[i]; + } + + return types; + } + + private Class<?> resolveType( ParameterizedType param, TypeVariable<?> var, TypeVariable<?>[] declaredTypes ) + { + if ( param.getActualTypeArguments( ).length < 1 ) + { + return null; + } + + for ( int i = 0; i < declaredTypes.length; i++ ) + { + if ( !TypeVariable.class.isInstance( param.getActualTypeArguments( )[i] ) + && declaredTypes[i].getName( ).equals( var.getName( ) ) ) + { + return (Class<?>) param.getActualTypeArguments( )[i]; + } + } + + return null; + } +} Modified: commons/proper/ognl/branches/new-cache-approach/src/test/java/org/apache/commons/ognl/TestOgnlRuntime.java URL: http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/test/java/org/apache/commons/ognl/TestOgnlRuntime.java?rev=1184935&r1=1184934&r2=1184935&view=diff ============================================================================== --- commons/proper/ognl/branches/new-cache-approach/src/test/java/org/apache/commons/ognl/TestOgnlRuntime.java (original) +++ commons/proper/ognl/branches/new-cache-approach/src/test/java/org/apache/commons/ognl/TestOgnlRuntime.java Sun Oct 16 21:27:18 2011 @@ -19,6 +19,7 @@ */ package org.apache.commons.ognl; +import org.apache.commons.ognl.internal.CacheException; import org.apache.commons.ognl.test.objects.BaseGeneric; import org.apache.commons.ognl.test.objects.Bean1; import org.apache.commons.ognl.test.objects.Bean2; @@ -361,7 +362,7 @@ public class TestOgnlRuntime */ @Test public void testOGNLParameterDiscovery( ) - throws NoSuchMethodException + throws NoSuchMethodException, CacheException { Method saveMethod = GenericParent.class.getMethod( "save", Object.class ); System.out.println( saveMethod ); Added: commons/proper/ognl/branches/new-cache-approach/src/test/java/org/apache/commons/ognl/internal/GenericMethodParameterTypeCacheTest.java URL: http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/test/java/org/apache/commons/ognl/internal/GenericMethodParameterTypeCacheTest.java?rev=1184935&view=auto ============================================================================== --- commons/proper/ognl/branches/new-cache-approach/src/test/java/org/apache/commons/ognl/internal/GenericMethodParameterTypeCacheTest.java (added) +++ commons/proper/ognl/branches/new-cache-approach/src/test/java/org/apache/commons/ognl/internal/GenericMethodParameterTypeCacheTest.java Sun Oct 16 21:27:18 2011 @@ -0,0 +1,34 @@ +package org.apache.commons.ognl.internal; + +import org.apache.commons.ognl.internal.entry.GenericMethodParameterTypeCacheEntry; +import org.apache.commons.ognl.internal.entry.GenericMethodParameterTypeFactory; +import org.apache.commons.ognl.test.objects.GameGeneric; +import org.junit.Assert; +import org.junit.Test; + +import java.io.Serializable; +import java.lang.reflect.Method; + +/** + * User: Maurizio Cucchiara + * Date: 10/16/11 + * Time: 9:44 AM + */ +public class GenericMethodParameterTypeCacheTest +{ + private ConcurrentHashMapCache<GenericMethodParameterTypeCacheEntry, Class<?>[]> cache = + new ConcurrentHashMapCache<GenericMethodParameterTypeCacheEntry, Class<?>[]>( new GenericMethodParameterTypeFactory( ) ); + + @Test + public void testGet( ) + throws NoSuchMethodException, CacheException + { + Method m = GameGeneric.class.getMethod( "setIds", Serializable[].class ); + Class type = GameGeneric.class; + Class<?>[] types = cache.get( new GenericMethodParameterTypeCacheEntry( m, type ) ); + + Assert.assertEquals( 1, types.length ); + Assert.assertEquals( Long[].class, types[0] ); + } + +} Modified: commons/proper/ognl/branches/new-cache-approach/src/test/java/org/apache/commons/ognl/test/OgnlTestCase.java URL: http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/test/java/org/apache/commons/ognl/test/OgnlTestCase.java?rev=1184935&r1=1184934&r2=1184935&view=diff ============================================================================== --- commons/proper/ognl/branches/new-cache-approach/src/test/java/org/apache/commons/ognl/test/OgnlTestCase.java (original) +++ commons/proper/ognl/branches/new-cache-approach/src/test/java/org/apache/commons/ognl/test/OgnlTestCase.java Sun Oct 16 21:27:18 2011 @@ -199,7 +199,7 @@ public abstract class OgnlTestCase } catch (Exception ex) { if (RuntimeException.class.isInstance(ex) && ex.getCause() != null && Exception.class.isAssignableFrom( ex.getCause().getClass())) { - ex = (Exception) ((RuntimeException) ex).getCause(); + ex = (Exception) ex.getCause( ); } if (testedResult instanceof Class) {