Modified: commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/TypeConverter.java URL: http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/TypeConverter.java?rev=1181012&r1=1181011&r2=1181012&view=diff ============================================================================== --- commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/TypeConverter.java (original) +++ commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/TypeConverter.java Mon Oct 10 15:13:25 2011 @@ -45,6 +45,7 @@ public interface TypeConverter * @return Converted value of type toType or TypeConverter.NoConversionPossible to indicate that the conversion was * not possible. */ - <T> T convertValue( Map<String, Object> context, Object target, Member member, String propertyName, Object value, Class<T> toType ); + <T> T convertValue( Map<String, Object> context, Object target, Member member, String propertyName, Object value, Class<T> toType ) + throws OgnlException; }
Added: commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/CacheEntryFactory.java URL: http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/CacheEntryFactory.java?rev=1181012&view=auto ============================================================================== --- commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/CacheEntryFactory.java (added) +++ commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/CacheEntryFactory.java Mon Oct 10 15:13:25 2011 @@ -0,0 +1,12 @@ +package org.apache.commons.ognl.internal; + +/** + * User: Maurizio Cucchiara + * Date: 10/8/11 + * Time: 7:57 PM + */ +public interface CacheEntryFactory<T, V> +{ + public V create( T key ) + throws CacheException; +} Added: commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/CacheException.java URL: http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/CacheException.java?rev=1181012&view=auto ============================================================================== --- commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/CacheException.java (added) +++ commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/CacheException.java Mon Oct 10 15:13:25 2011 @@ -0,0 +1,17 @@ +package org.apache.commons.ognl.internal; + +import org.apache.commons.ognl.OgnlException; + +/** + * User: Maurizio Cucchiara + * Date: 10/9/11 + * Time: 6:14 PM + */ +public class CacheException + extends OgnlException +{ + public CacheException( Throwable e ) + { + super(e.getMessage(),e); + } +} Modified: commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ClassCache.java URL: http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ClassCache.java?rev=1181012&r1=1181011&r2=1181012&view=diff ============================================================================== --- commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ClassCache.java (original) +++ commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ClassCache.java Mon Oct 10 15:13:25 2011 @@ -24,7 +24,7 @@ import org.apache.commons.ognl.ClassCach /** * This is a highly specialized map for storing values keyed by Class objects. */ -public interface ClassCache +public interface ClassCache<V> { void setClassInspector( ClassCacheInspector inspector ); @@ -33,7 +33,11 @@ public interface ClassCache int getSize(); - <T> T get( Class<?> key ); + V get( Class<?> key, CacheEntryFactory<Class<?>, V> cacheEntryFactory ) + throws CacheException; - <T> T put( Class<?> key, T value ); + V get( Class<?> key ) + throws CacheException; + + V put( Class<?> key, V value ); } Added: commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ClassCacheEntryFactory.java URL: http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ClassCacheEntryFactory.java?rev=1181012&view=auto ============================================================================== --- commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ClassCacheEntryFactory.java (added) +++ commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ClassCacheEntryFactory.java Mon Oct 10 15:13:25 2011 @@ -0,0 +1,14 @@ +package org.apache.commons.ognl.internal; + +/** + * User: Maurizio Cucchiara + * Date: 10/8/11 + * Time: 7:58 PM + */ +public interface ClassCacheEntryFactory<V> + extends CacheEntryFactory<Class<?>, V> +{ + V create( Class<?> key ) + throws CacheException; + +} Added: commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ClassCacheHandler.java URL: http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ClassCacheHandler.java?rev=1181012&view=auto ============================================================================== --- commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ClassCacheHandler.java (added) +++ commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ClassCacheHandler.java Mon Oct 10 15:13:25 2011 @@ -0,0 +1,75 @@ +package org.apache.commons.ognl.internal; + +/** + * User: Maurizio Cucchiara + * Date: 10/9/11 + * Time: 1:02 PM + */ +public class ClassCacheHandler +{ + + private ClassCacheHandler( ) + { + } + + public static <T> T getHandler( Class<?> forClass, ClassCache<T> handlers ) + throws CacheException + { + T answer; + + synchronized ( handlers ) + { + if ( ( answer = handlers.get( forClass ) ) == null ) + { + Class<?> keyFound; + + if ( forClass.isArray( ) ) + { + answer = handlers.get( Object[].class ); + keyFound = null; + } + else + { + keyFound = forClass; + outer: + for ( Class<?> c = forClass; c != null; c = c.getSuperclass( ) ) + { + answer = handlers.get( c ); + if ( answer == null ) + { + Class<?>[] interfaces = c.getInterfaces( ); + for ( Class<?> iface : interfaces ) + { + answer = handlers.get( iface ); + if ( answer == null ) + { + /* Try super-interfaces */ + answer = getHandler( iface ,handlers); + } + if ( answer != null ) + { + keyFound = iface; + break outer; + } + } + } + else + { + keyFound = c; + break; + } + } + } + if ( answer != null ) + { + if ( keyFound != forClass ) + { + handlers.put( forClass, answer ); + } + } + } + } + return answer; + + } +} Modified: commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ClassCacheImpl.java URL: http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ClassCacheImpl.java?rev=1181012&r1=1181011&r2=1181012&view=diff ============================================================================== --- commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ClassCacheImpl.java (original) +++ commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ClassCacheImpl.java Mon Oct 10 15:13:25 2011 @@ -26,8 +26,8 @@ import java.util.Arrays; /** * Implementation of {@link ClassCache}. */ -public class ClassCacheImpl - implements ClassCache +public class ClassCacheImpl<V> + implements ClassCache<V> { /* this MUST be a power of 2 */ @@ -36,15 +36,20 @@ public class ClassCacheImpl /* ...and now you see why. The table size is used as a mask for generating hashes */ private static final int TABLE_SIZE_MASK = TABLE_SIZE - 1; - private Entry<?>[] _table; + private Entry<Class<?>,V>[] _table = new Entry[TABLE_SIZE]; private ClassCacheInspector _classInspector; private int _size = 0; + private CacheEntryFactory<Class<?>, V> factory; + + public ClassCacheImpl( CacheEntryFactory<Class<?>, V> factory ) + { + this.factory = factory; + } public ClassCacheImpl() { - _table = new Entry[TABLE_SIZE]; } /** @@ -79,55 +84,61 @@ public class ClassCacheImpl /** * {@inheritDoc} */ - public final <T> T get( Class<?> key ) + public final V get( Class<?> key) + throws CacheException + { + return get( key, null ); + } + + public final V get( Class<?> key, CacheEntryFactory<Class<?>, V> cacheEntryFactory ) + throws CacheException { int i = key.hashCode() & TABLE_SIZE_MASK; - Entry<?> entry = _table[i]; + Entry<Class<?>,V> entry = _table[i]; while ( entry != null ) { if ( key == entry.getKey() ) { - @SuppressWarnings( "unchecked" ) // guaranteed by key == entry.getKey() - T result = (T) entry.getValue(); - return result; + return entry.getValue(); } entry = entry.getNext(); } - + if ( factory != null ) + { + return put(key, factory.create(key)); + } return null; } /** * {@inheritDoc} */ - public final <T> T put( Class<?> key, T value ) + public final V put( Class<?> key, V value ) { if ( _classInspector != null && !_classInspector.shouldCache( key ) ) { return value; } - T result = null; + V result = null; int i = key.hashCode() & TABLE_SIZE_MASK; - Entry<?> entry = _table[i]; + Entry<Class<?>,V> entry = _table[i]; if ( entry == null ) { - _table[i] = new Entry<T>( key, value ); + _table[i] = new Entry<Class<?>,V>( key, value ); _size++; } else { if ( key == entry.getKey() ) { - @SuppressWarnings( "unchecked" ) // guaranteed by key == entry.getKey() - Entry<T> current = (Entry<T>) entry; - result = current.getValue(); - current.setValue( value ); + result = entry.getValue( ); + entry.setValue( value ); } else { @@ -136,17 +147,15 @@ public class ClassCacheImpl if ( key == entry.getKey() ) { /* replace value */ - @SuppressWarnings( "unchecked" ) // guaranteed by key == entry.getKey() - Entry<T> current = (Entry<T>) entry; - result = current.getValue(); - current.setValue( value ); + result = entry.getValue( ); + entry.setValue( value ); break; } if ( entry.getNext() == null ) { /* add value */ - entry.setNext( new Entry<T>( key, value ) ); + entry.setNext( new Entry<Class<?>,V>( key, value ) ); break; } Added: 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=1181012&view=auto ============================================================================== --- commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ConcurrentClassCache.java (added) +++ commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ConcurrentClassCache.java Mon Oct 10 15:13:25 2011 @@ -0,0 +1,69 @@ +package org.apache.commons.ognl.internal; + +import org.apache.commons.ognl.ClassCacheInspector; + +import java.util.concurrent.ConcurrentHashMap; + +/** + * User: Maurizio Cucchiara + * Date: 10/8/11 + * Time: 8:04 PM + */ +public class ConcurrentClassCache<V> + implements ClassCache<V> +{ + 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() + { + cache.clear(); + } + + public int getSize() + { + return cache.size(); + } + + public V get( Class<?> key ) + throws CacheException + { + return get( key, null ); + } + + public V get( Class<?> key, CacheEntryFactory<Class<?>, V> cacheEntryFactory ) + throws CacheException + { + V v = cache.get( key ); + if ( v == null && cacheEntryFactory != null ) + { + return put( key, cacheEntryFactory.create( key ) ); + } + return v; + } + + public V put( Class<?> key, V value ) + { + if ( inspector != null && !inspector.shouldCache( key ) ) + { + return value; + } + V collision = cache.putIfAbsent( key, value ); + if ( collision != null ) + { + return collision; + } + return value; + } +} Modified: commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/Entry.java URL: http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/Entry.java?rev=1181012&r1=1181011&r2=1181012&view=diff ============================================================================== --- commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/Entry.java (original) +++ commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/Entry.java Mon Oct 10 15:13:25 2011 @@ -22,42 +22,42 @@ package org.apache.commons.ognl.internal /** * Used by {@link ClassCacheImpl} to store entries in the cache. */ -final class Entry<T> +class Entry<K,V> { - private Entry<?> next; + private Entry<K,V> next; - private final Class<?> key; + private final K key; - private T value; + private V value; - public Entry( Class<?> key, T value ) + public Entry( K key, V value ) { this.key = key; this.value = value; } - public Class<?> getKey() + public K getKey() { return key; } - public T getValue() + public V getValue() { return value; } - public void setValue( T value ) + public void setValue( V value ) { this.value = value; } - public Entry<?> getNext() + public Entry<K,V> getNext() { return next; } - public void setNext( Entry<?> next ) + public void setNext( Entry<K,V> next ) { this.next = next; }
