Author: mcucchiara
Date: Mon Oct 10 15:13:25 2011
New Revision: 1181012
URL: http://svn.apache.org/viewvc?rev=1181012&view=rev
Log:
OGNL-20 [Partial] Performance - Replace synchronized blocks with
ConcurrentHashMap
Added:
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/CacheEntryFactory.java
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/CacheException.java
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ClassCacheEntryFactory.java
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ClassCacheHandler.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/DefaultTypeConverter.java
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/EvaluationPool.java
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/MethodAccessor.java
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/ObjectArrayPool.java
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/ObjectMethodAccessor.java
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/Ognl.java
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/OgnlOps.java
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/TypeConverter.java
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ClassCache.java
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/ClassCacheImpl.java
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/internal/Entry.java
Modified:
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/DefaultTypeConverter.java
URL:
http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/DefaultTypeConverter.java?rev=1181012&r1=1181011&r2=1181012&view=diff
==============================================================================
---
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/DefaultTypeConverter.java
(original)
+++
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/DefaultTypeConverter.java
Mon Oct 10 15:13:25 2011
@@ -33,6 +33,7 @@ public class DefaultTypeConverter
{
public <T> T convertValue( Map<String, Object> context, Object value,
Class<T> toType )
+ throws OgnlException
{
@SuppressWarnings( "unchecked" ) // type checking performed in
OgnlOps.convertValue( value, toType )
T ret = (T) OgnlOps.convertValue( value, toType );
@@ -44,6 +45,7 @@ public class DefaultTypeConverter
*/
public <T> T convertValue( Map<String, Object> context, Object target,
Member member, String propertyName, Object value,
Class<T> toType )
+ throws OgnlException
{
return convertValue( context, value, toType );
}
Modified:
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/EvaluationPool.java
URL:
http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/EvaluationPool.java?rev=1181012&r1=1181011&r2=1181012&view=diff
==============================================================================
---
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/EvaluationPool.java
(original)
+++
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/EvaluationPool.java
Mon Oct 10 15:13:25 2011
@@ -19,34 +19,22 @@ package org.apache.commons.ognl;
* under the License.
*/
-import java.util.ArrayList;
import java.util.List;
+/**
+ * @deprecated evaluation-pooling now relies on the jvm garbage collection
+ */
public final class EvaluationPool
{
- private final List<Evaluation> evaluations = new ArrayList<Evaluation>();
-
- private int size = 0;
-
- private int created = 0;
-
- private int recovered = 0;
-
- private int recycled = 0;
-
- public EvaluationPool()
+ public EvaluationPool( )
{
this( 0 );
}
public EvaluationPool( int initialSize )
{
- super();
- for ( int i = 0; i < initialSize; i++ )
- {
- evaluations.add( new Evaluation( null, null ) );
- }
- created = size = initialSize;
+ super( );
+ // do not init object pooling
}
/**
@@ -59,98 +47,87 @@ public final class EvaluationPool
}
/**
- * Returns an Evaluation that contains the node, source and whether it is
a set operation. If there are no
- * Evaluation objects in the pool one is created and returned.
+ * Returns an Evaluation that contains the node, source and whether it
+ * is a set operation.
*/
- public synchronized Evaluation create( SimpleNode node, Object source,
boolean setOperation )
+ public Evaluation create( SimpleNode node, Object source, boolean
setOperation )
{
- Evaluation result;
-
- if ( size > 0 )
- {
- result = evaluations.remove( size - 1 );
- result.init( node, source, setOperation );
- size--;
- recovered++;
- }
- else
- {
- result = new Evaluation( node, source, setOperation );
- created++;
- }
- return result;
+ // synchronization is removed as we do not rely anymore on the
in-house object pooling
+ return new Evaluation( node, source, setOperation );
}
/**
* Recycles an Evaluation
+ *
+ * @deprecated object-pooling now relies on the jvm garbage collection
*/
- public synchronized void recycle( Evaluation value )
+ public void recycle( Evaluation value )
{
- if ( value != null )
- {
- value.reset();
- evaluations.add( value );
- size++;
- recycled++;
- }
+ // no need of recycling, we rely on the garbage collection efficiency
}
/**
- * Recycles an of Evaluation and all of it's siblings and children.
+ * Recycles an of Evaluation and all of it's siblings
+ * and children.
+ *
+ * @deprecated object-pooling now relies on the jvm garbage collection
*/
public void recycleAll( Evaluation value )
{
- if ( value != null )
- {
- recycleAll( value.getNext() );
- recycleAll( value.getFirstChild() );
- recycle( value );
- }
+ // no need of recycling, we rely on the garbage collection efficiency
}
/**
* Recycles a List of Evaluation objects
+ *
+ * @deprecated object-pooling now relies on the jvm garbage collection
*/
- public void recycleAll( List<Evaluation> value )
+ public void recycleAll( List value )
{
- if ( value != null )
- {
- for ( int i = 0, icount = value.size(); i < icount; i++ )
- {
- recycle( value.get( i ) );
- }
- }
+ // no need of recycling, we rely on the garbage collection efficiency
}
/**
* Returns the number of items in the pool
+ *
+ * @deprecated object-pooling now relies on the jvm garbage collection
*/
- public int getSize()
+ public int getSize( )
{
- return size;
+ return 0;
}
/**
- * Returns the number of items this pool has created since it's
construction.
+ * Returns the number of items this pool has created since
+ * it's construction.
+ *
+ * @deprecated object-pooling now relies on the jvm garbage collection
*/
- public int getCreatedCount()
+ public int getCreatedCount( )
{
- return created;
+ return 0;
}
/**
- * Returns the number of items this pool has recovered from the pool since
its construction.
+ * Returns the number of items this pool has recovered from
+ * the pool since its construction.
+ *
+ * @deprecated object-pooling now relies on the jvm garbage collection
*/
- public int getRecoveredCount()
+ public int getRecoveredCount( )
{
- return recovered;
+ return 0;
}
/**
- * Returns the number of items this pool has recycled since it's
construction.
+ * Returns the number of items this pool has recycled since
+ * it's construction.
+ *
+ * @deprecated object-pooling now relies on the jvm garbage collection
*/
- public int getRecycledCount()
+ public int getRecycledCount( )
{
- return recycled;
+ return 0;
}
}
+
Modified:
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/MethodAccessor.java
URL:
http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/MethodAccessor.java?rev=1181012&r1=1181011&r2=1181012&view=diff
==============================================================================
---
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/MethodAccessor.java
(original)
+++
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/MethodAccessor.java
Mon Oct 10 15:13:25 2011
@@ -41,7 +41,7 @@ public interface MethodAccessor
* @exception MethodFailedException if there is an error calling the method
*/
Object callStaticMethod( Map<String, Object> context, Class<?>
targetClass, String methodName, Object[] args )
- throws MethodFailedException;
+ throws OgnlException;
/**
* Calls the method named with the arguments given.
@@ -54,5 +54,5 @@ public interface MethodAccessor
* @exception MethodFailedException if there is an error calling the method
*/
Object callMethod( Map<String, Object> context, Object target, String
methodName, Object[] args )
- throws MethodFailedException;
+ throws OgnlException;
}
Modified:
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/ObjectArrayPool.java
URL:
http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/ObjectArrayPool.java?rev=1181012&r1=1181011&r2=1181012&view=diff
==============================================================================
---
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/ObjectArrayPool.java
(original)
+++
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/ObjectArrayPool.java
Mon Oct 10 15:13:25 2011
@@ -19,147 +19,26 @@ package org.apache.commons.ognl;
* under the License.
*/
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
+/**
+ * This class was previously intended to produce performance improvement.<br>
+ * This hand-made object pooling is now a bottleneck under high load.<br>
+ * We now rely on the new jvm garbage collection improvements to handle object
allocation efficiently.
+ *
+ * @deprecated object-pooling now relies on the jvm garbage collection
+ */
public final class ObjectArrayPool
{
- private final IntHashMap<Integer, SizePool> pools = new
IntHashMap<Integer, SizePool>( 23 );
-
- public static class SizePool
+ public ObjectArrayPool( )
{
- private final List<Object[]> arrays = new ArrayList<Object[]>();
-
- private int arraySize;
-
- private int size;
-
- private int created = 0;
-
- private int recovered = 0;
-
- private int recycled = 0;
-
- public SizePool( int arraySize )
- {
- this( arraySize, 0 );
- }
-
- public SizePool( int arraySize, int initialSize )
- {
- super();
- this.arraySize = arraySize;
- for ( int i = 0; i < initialSize; i++ )
- {
- arrays.add( new Object[arraySize] );
- }
- created = size = initialSize;
- }
-
- public int getArraySize()
- {
- return arraySize;
- }
-
- public Object[] create()
- {
- Object[] result;
-
- if ( size > 0 )
- {
- result = arrays.remove( size - 1 );
- size--;
- recovered++;
- }
- else
- {
- result = new Object[arraySize];
- created++;
- }
- return result;
- }
-
- public synchronized void recycle( Object[] value )
- {
- if ( value != null )
- {
- if ( value.length != arraySize )
- {
- throw new IllegalArgumentException( "recycled array size "
+ value.length
- + " inappropriate for pool array size " + arraySize );
- }
- Arrays.fill( value, null );
- arrays.add( value );
- size++;
- recycled++;
- }
- else
- {
- throw new IllegalArgumentException( "cannot recycle null
object" );
- }
- }
-
- /**
- * Returns the number of items in the pool
- */
- public int getSize()
- {
- return size;
- }
-
- /**
- * Returns the number of items this pool has created since it's
construction.
- */
- public int getCreatedCount()
- {
- return created;
- }
-
- /**
- * Returns the number of items this pool has recovered from the pool
since its construction.
- */
- public int getRecoveredCount()
- {
- return recovered;
- }
-
- /**
- * Returns the number of items this pool has recycled since it's
construction.
- */
- public int getRecycledCount()
- {
- return recycled;
- }
- }
-
- public ObjectArrayPool()
- {
- super();
- }
-
- public IntHashMap<Integer, SizePool> getSizePools()
- {
- return pools;
- }
-
- public synchronized SizePool getSizePool( int arraySize )
- {
- SizePool result = pools.get( arraySize );
-
- if ( result == null )
- {
- pools.put( arraySize, result = new SizePool( arraySize ) );
- }
- return result;
+ super( );
}
- public synchronized Object[] create( int arraySize )
+ public Object[] create( int arraySize )
{
- return getSizePool( arraySize ).create();
+ return new Object[arraySize];
}
- public synchronized Object[] create( Object singleton )
+ public Object[] create( Object singleton )
{
Object[] result = create( 1 );
@@ -167,7 +46,7 @@ public final class ObjectArrayPool
return result;
}
- public synchronized Object[] create( Object object1, Object object2 )
+ public Object[] create( Object object1, Object object2 )
{
Object[] result = create( 2 );
@@ -176,7 +55,7 @@ public final class ObjectArrayPool
return result;
}
- public synchronized Object[] create( Object object1, Object object2,
Object object3 )
+ public Object[] create( Object object1, Object object2, Object object3 )
{
Object[] result = create( 3 );
@@ -186,7 +65,7 @@ public final class ObjectArrayPool
return result;
}
- public synchronized Object[] create( Object object1, Object object2,
Object object3, Object object4 )
+ public Object[] create( Object object1, Object object2, Object object3,
Object object4 )
{
Object[] result = create( 4 );
@@ -197,7 +76,7 @@ public final class ObjectArrayPool
return result;
}
- public synchronized Object[] create( Object object1, Object object2,
Object object3, Object object4, Object object5 )
+ public Object[] create( Object object1, Object object2, Object object3,
Object object4, Object object5 )
{
Object[] result = create( 5 );
@@ -209,11 +88,11 @@ public final class ObjectArrayPool
return result;
}
- public synchronized void recycle( Object[] value )
+ /**
+ * @deprecated object-pooling now relies on the jvm garbage collection
+ */
+ public void recycle( Object[] value )
{
- if ( value != null )
- {
- getSizePool( value.length ).recycle( value );
- }
+ // no need of recycling, we rely on the garbage collection efficiency
}
}
Modified:
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/ObjectMethodAccessor.java
URL:
http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/ObjectMethodAccessor.java?rev=1181012&r1=1181011&r2=1181012&view=diff
==============================================================================
---
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/ObjectMethodAccessor.java
(original)
+++
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/ObjectMethodAccessor.java
Mon Oct 10 15:13:25 2011
@@ -38,7 +38,7 @@ public class ObjectMethodAccessor
* {@inheritDoc}
*/
public Object callStaticMethod( Map<String, Object> context, Class<?>
targetClass, String methodName, Object[] args )
- throws MethodFailedException
+ throws OgnlException
{
List<Method> methods = OgnlRuntime.getMethods( targetClass,
methodName, true );
@@ -50,7 +50,7 @@ public class ObjectMethodAccessor
* {@inheritDoc}
*/
public Object callMethod( Map<String, Object> context, Object target,
String methodName, Object[] args )
- throws MethodFailedException
+ throws OgnlException
{
Class<?> targetClass = ( target == null ) ? null : target.getClass();
List<Method> methods = OgnlRuntime.getMethods( targetClass,
methodName, false );
Modified:
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/Ognl.java
URL:
http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/Ognl.java?rev=1181012&r1=1181011&r2=1181012&view=diff
==============================================================================
---
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/Ognl.java
(original)
+++
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/Ognl.java
Mon Oct 10 15:13:25 2011
@@ -51,7 +51,7 @@ import java.util.Map;
* <p>
* This will parse the expression given and evaluate it against the root
object given, returning the result. If there is
* an error in the expression, such as the property is not found, the
exception is encapsulated into an
- * {@link ognl.OgnlException OgnlException}.
+ * {@link org.apache.commons.ognl.OgnlException OgnlException}.
* </p>
* <p>
* Other more sophisticated uses of Ognl can pre-parse expressions. This
provides two advantages: in the case of
@@ -126,13 +126,13 @@ public abstract class Ognl
}
/**
- * Parses and compiles the given expression using the {@link
ognl.enhance.OgnlExpressionCompiler} returned from
- * {@link ognl.OgnlRuntime#getCompiler()}.
+ * Parses and compiles the given expression using the {@link
org.apache.commons.ognl.enhance.OgnlExpressionCompiler} returned from
+ * {@link org.apache.commons.ognl.OgnlRuntime#getCompiler()}.
*
* @param context The context to use.
* @param root The root object for the given expression.
* @param expression The expression to compile.
- * @return The node with a compiled accessor set on {@link
ognl.Node#getAccessor()} if compilation was successfull.
+ * @return The node with a compiled accessor set on {@link
org.apache.commons.ognl.Node#getAccessor()} if compilation was successfull.
* In instances where compilation wasn't possible because of a
partially null expression the
* {@link ExpressionAccessor} instance may be null and the
compilation of this expression still possible at
* some as yet indertermined point in the future.
@@ -471,6 +471,7 @@ public abstract class Ognl
* @return The value.
*/
public static <T> T getValue( ExpressionAccessor expression, OgnlContext
context, Object root, Class<T> resultType )
+ throws OgnlException
{
return getTypeConverter( context ).convertValue( context, root, null,
null, expression.get( context, root ),
resultType );
Modified:
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/OgnlOps.java
URL:
http://svn.apache.org/viewvc/commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/OgnlOps.java?rev=1181012&r1=1181011&r2=1181012&view=diff
==============================================================================
---
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/OgnlOps.java
(original)
+++
commons/proper/ognl/branches/new-cache-approach/src/main/java/org/apache/commons/ognl/OgnlOps.java
Mon Oct 10 15:13:25 2011
@@ -431,71 +431,85 @@ public abstract class OgnlOps
}
public static Object toArray( char value, Class<?> toType )
+ throws OgnlException
{
return toArray( new Character( value ), toType );
}
public static Object toArray( byte value, Class<?> toType )
+ throws OgnlException
{
return toArray( new Byte( value ), toType );
}
public static Object toArray( int value, Class<?> toType )
+ throws OgnlException
{
return toArray( new Integer( value ), toType );
}
public static Object toArray( long value, Class<?> toType )
+ throws OgnlException
{
return toArray( new Long( value ), toType );
}
public static Object toArray( float value, Class<?> toType )
+ throws OgnlException
{
return toArray( new Float( value ), toType );
}
public static Object toArray( double value, Class<?> toType )
+ throws OgnlException
{
return toArray( new Double( value ), toType );
}
public static Object toArray( boolean value, Class<?> toType )
+ throws OgnlException
{
return toArray( Boolean.valueOf( value ), toType );
}
public static <T> Object convertValue( char value, Class<T> toType )
+ throws OgnlException
{
return convertValue( new Character( value ), toType );
}
public static <T> Object convertValue( byte value, Class<T> toType )
+ throws OgnlException
{
return convertValue( new Byte( value ), toType );
}
public static <T> Object convertValue( int value, Class<T> toType )
+ throws OgnlException
{
return convertValue( new Integer( value ), toType );
}
public static <T> Object convertValue( long value, Class<T> toType )
+ throws OgnlException
{
return convertValue( new Long( value ), toType );
}
public static <T> Object convertValue( float value, Class<T> toType )
+ throws OgnlException
{
return convertValue( new Float( value ), toType );
}
public static <T> Object convertValue( double value, Class<T> toType )
+ throws OgnlException
{
return convertValue( new Double( value ), toType );
}
public static <T> Object convertValue( boolean value, Class<T> toType )
+ throws OgnlException
{
return convertValue( Boolean.valueOf( value ), toType );
}
@@ -503,36 +517,43 @@ public abstract class OgnlOps
// //////////////////////////////////////////////////////////////
public static <T> Object convertValue( char value, Class<T> toType,
boolean preventNull )
+ throws OgnlException
{
return convertValue( new Character( value ), toType, preventNull );
}
public static <T> Object convertValue( byte value, Class<T> toType,
boolean preventNull )
+ throws OgnlException
{
return convertValue( new Byte( value ), toType, preventNull );
}
public static <T> Object convertValue( int value, Class<T> toType, boolean
preventNull )
+ throws OgnlException
{
return convertValue( new Integer( value ), toType, preventNull );
}
public static <T> Object convertValue( long value, Class<T> toType,
boolean preventNull )
+ throws OgnlException
{
return convertValue( new Long( value ), toType, preventNull );
}
public static <T> Object convertValue( float value, Class<T> toType,
boolean preventNull )
+ throws OgnlException
{
return convertValue( new Float( value ), toType, preventNull );
}
public static <T> Object convertValue( double value, Class<T> toType,
boolean preventNull )
+ throws OgnlException
{
return convertValue( new Double( value ), toType, preventNull );
}
public static <T> Object convertValue( boolean value, Class<T> toType,
boolean preventNull )
+ throws OgnlException
{
return convertValue( Boolean.valueOf( value ), toType, preventNull );
}
@@ -540,36 +561,43 @@ public abstract class OgnlOps
// ///////////////////////////////////////////////////////////////
public static Object toArray( char value, Class<?> toType, boolean
preventNull )
+ throws OgnlException
{
return toArray( new Character( value ), toType, preventNull );
}
public static Object toArray( byte value, Class<?> toType, boolean
preventNull )
+ throws OgnlException
{
return toArray( new Byte( value ), toType, preventNull );
}
public static Object toArray( int value, Class<?> toType, boolean
preventNull )
+ throws OgnlException
{
return toArray( new Integer( value ), toType, preventNull );
}
public static Object toArray( long value, Class<?> toType, boolean
preventNull )
+ throws OgnlException
{
return toArray( new Long( value ), toType, preventNull );
}
public static Object toArray( float value, Class<?> toType, boolean
preventNull )
+ throws OgnlException
{
return toArray( new Float( value ), toType, preventNull );
}
public static Object toArray( double value, Class<?> toType, boolean
preventNull )
+ throws OgnlException
{
return toArray( new Double( value ), toType, preventNull );
}
public static Object toArray( boolean value, Class<?> toType, boolean
preventNull )
+ throws OgnlException
{
return toArray( Boolean.valueOf( value ), toType, preventNull );
}
@@ -583,21 +611,24 @@ public abstract class OgnlOps
* @return converted value of the type given, or value if the value cannot
be converted to the given type.
*/
public static Object convertValue( Object value, Class<?> toType )
+ throws OgnlException
{
return convertValue( value, toType, false );
}
public static Object toArray( Object value, Class<?> toType )
+ throws OgnlException
{
return toArray( value, toType, false );
}
public static Object toArray( Object value, Class<?> toType, boolean
preventNulls )
+ throws OgnlException
{
if ( value == null )
return null;
- Object result = null;
+ Object result;
if ( value.getClass().isArray() && toType.isAssignableFrom(
value.getClass().getComponentType() ) )
{
@@ -633,6 +664,7 @@ public abstract class OgnlOps
}
public static <T> Object convertValue( Object value, Class<T> toType,
boolean preventNulls )
+ throws OgnlException
{
Object result = null;