Author: cbrisson
Date: Tue Feb 26 14:30:46 2019
New Revision: 1854386
URL: http://svn.apache.org/viewvc?rev=1854386&view=rev
Log:
[engine] Merge branch VELOCITY-892
Added:
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/TypeConversionHandler.java
- copied unchanged from r1854372,
velocity/engine/branches/VELOCITY-892/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/TypeConversionHandler.java
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/TypeConversionHandlerImpl.java
- copied, changed from r1854372,
velocity/engine/branches/VELOCITY-892/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/TypeConversionHandlerImpl.java
Removed:
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/Pair.java
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/ConversionHandlerImpl.java
Modified:
velocity/engine/trunk/ (props changed)
velocity/engine/trunk/pom.xml
velocity/engine/trunk/velocity-engine-core/pom.xml
velocity/engine/trunk/velocity-engine-core/src/main/java/ (props changed)
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeConstants.java
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeServices.java
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/ClassMap.java
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/ConversionHandler.java
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/IntrospectionUtils.java
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/Introspector.java
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/IntrospectorBase.java
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/IntrospectorCache.java
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/MethodMap.java
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/UberspectImpl.java
velocity/engine/trunk/velocity-engine-core/src/main/resources/org/apache/velocity/runtime/defaults/velocity.properties
velocity/engine/trunk/velocity-engine-core/src/test/java/ (props changed)
velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/util/introspection/ConversionHandlerTestCase.java
Propchange: velocity/engine/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Feb 26 14:30:46 2019
@@ -1,3 +1,4 @@
/velocity/engine/branches/2.0_Exp:958513,991637-995742
+/velocity/engine/branches/VELOCITY-892:1844076-1854372
/velocity/engine/branches/VELOCITY-898:1843220-1843786
/velocity/engine/trunk:992133,1032159
Modified: velocity/engine/trunk/pom.xml
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/pom.xml?rev=1854386&r1=1854385&r2=1854386&view=diff
==============================================================================
--- velocity/engine/trunk/pom.xml (original)
+++ velocity/engine/trunk/pom.xml Tue Feb 26 14:30:46 2019
@@ -45,8 +45,8 @@
<slf4j.version>1.7.26</slf4j.version>
<surefire.plugin.version>2.19.1</surefire.plugin.version>
<jira.browse.url>https://issues.apache.org/jira/browse</jira.browse.url>
- <maven.compiler.source>1.7</maven.compiler.source>
- <maven.compiler.target>1.7</maven.compiler.target>
+ <maven.compiler.source>1.8</maven.compiler.source>
+ <maven.compiler.target>1.8</maven.compiler.target>
</properties>
<!-- java 8 doclint checks are too strict for our current javadoc state...
-->
@@ -144,6 +144,9 @@
<enforceBytecodeVersion>
<maxJdkVersion>${maven.compiler.target}</maxJdkVersion>
</enforceBytecodeVersion>
+ <requireJavaVersion>
+ <version>[1.8,)</version>
+ </requireJavaVersion>
</rules>
<fail>true</fail>
</configuration>
Modified: velocity/engine/trunk/velocity-engine-core/pom.xml
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/pom.xml?rev=1854386&r1=1854385&r2=1854386&view=diff
==============================================================================
--- velocity/engine/trunk/velocity-engine-core/pom.xml (original)
+++ velocity/engine/trunk/velocity-engine-core/pom.xml Tue Feb 26 14:30:46 2019
@@ -35,6 +35,8 @@
<!-- command line switch -Dparser.nodefiles=true generates AST Node
classes (new structures added to parser) -->
<parser.nodefiles>false</parser.nodefiles>
+
+ <parser.debug>false</parser.debug>
<!-- You can modify those properties locally to test
the DataSourceResourceLoader against other engines.
@@ -169,9 +171,9 @@
<buildParser>true</buildParser>
<buildNodeFiles>${parser.nodefiles}</buildNodeFiles>
<multi>true</multi>
- <debugParser>false</debugParser>
- <debugLookAhead>false</debugLookAhead>
- <debugTokenManager>false</debugTokenManager>
+ <debugParser>${parser.debug}</debugParser>
+ <debugLookAhead>${parser.debug}</debugLookAhead>
+ <debugTokenManager>${parser.debug}</debugTokenManager>
<jdkVersion>${maven.compiler.target}</jdkVersion>
<nodeUsesParser>true</nodeUsesParser>
<nodePackage>org.apache.velocity.runtime.parser.node</nodePackage>
Propchange: velocity/engine/trunk/velocity-engine-core/src/main/java/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Feb 26 14:30:46 2019
@@ -1,4 +1,5 @@
/velocity/engine/branches/2.0_Exp/src/java:958513,991637-995742
/velocity/engine/branches/2.0_Exp/velocity-engine-core/src/main/java:958513
+/velocity/engine/branches/VELOCITY-892/velocity-engine-core/src/main/java:1844076-1854372
/velocity/engine/branches/VELOCITY-898/velocity-engine-core/src/main/java:1843220-1843786
/velocity/engine/trunk/src/java:1032134
Modified:
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeConstants.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeConstants.java?rev=1854386&r1=1854385&r2=1854386&view=diff
==============================================================================
---
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeConstants.java
(original)
+++
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeConstants.java
Tue Feb 26 14:30:46 2019
@@ -252,22 +252,16 @@ public interface RuntimeConstants
/*
* ----------------------------------------------------------------------
- * G E N E R A L R U N T I M E C O N F I G U R A T I O N
+ * I N T R O S P E C T I O N C O N F I G U R A T I O N
* ----------------------------------------------------------------------
*/
- /** Switch for the interpolation facility for string literals. */
- String INTERPOLATE_STRINGLITERALS = "runtime.interpolate.string.literals";
-
- /** The character encoding for the templates. Used by the parser in
processing the input streams. */
- String INPUT_ENCODING = "input.encoding";
-
- /** Default Encoding is UTF-8. */
- String ENCODING_DEFAULT = "UTF-8";
-
/** key name for uberspector. Multiple classnames can be specified,in
which case uberspectors will be chained. */
String UBERSPECT_CLASSNAME = "runtime.introspector.uberspect";
+ /** key for Conversion Manager instance */
+ String CONVERSION_HANDLER_INSTANCE = "runtime.conversion.handler.instance";
+
/** key for Conversion Manager class */
String CONVERSION_HANDLER_CLASS = "runtime.conversion.handler.class";
@@ -277,6 +271,22 @@ public interface RuntimeConstants
/** A comma separated list of classes to restrict access to in the
SecureIntrospector. */
String INTROSPECTOR_RESTRICT_CLASSES = "introspector.restrict.classes";
+
+ /*
+ * ----------------------------------------------------------------------
+ * G E N E R A L R U N T I M E C O N F I G U R A T I O N
+ * ----------------------------------------------------------------------
+ */
+
+ /** Switch for the interpolation facility for string literals. */
+ String INTERPOLATE_STRINGLITERALS = "runtime.interpolate.string.literals";
+
+ /** The character encoding for the templates. Used by the parser in
processing the input streams. */
+ String INPUT_ENCODING = "input.encoding";
+
+ /** Default Encoding is UTF-8. */
+ String ENCODING_DEFAULT = "UTF-8";
+
/** Switch for ignoring nulls in math equations vs throwing exceptions. */
String STRICT_MATH = "runtime.strict.math";
Modified:
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeServices.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeServices.java?rev=1854386&r1=1854385&r2=1854386&view=diff
==============================================================================
---
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeServices.java
(original)
+++
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/RuntimeServices.java
Tue Feb 26 14:30:46 2019
@@ -110,7 +110,7 @@ public interface RuntimeServices
* @param key
* @param value
*/
- void addProperty(String key, Object value);
+ void addProperty(String key, Object value);
/**
* Clear the values pertaining to a particular
Modified:
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/ClassMap.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/ClassMap.java?rev=1854386&r1=1854385&r2=1854386&view=diff
==============================================================================
---
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/ClassMap.java
(original)
+++
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/ClassMap.java
Tue Feb 26 14:30:46 2019
@@ -73,7 +73,7 @@ public class ClassMap
* @param conversionHandler conversion handler
* @since 2.0
*/
- public ClassMap(final Class clazz, final Logger log, final
ConversionHandler conversionHandler)
+ public ClassMap(final Class clazz, final Logger log, final
TypeConversionHandler conversionHandler)
{
this.clazz = clazz;
this.log = log;
@@ -121,7 +121,7 @@ public class ClassMap
* are taken from all the public methods
* that our class, its parents and their implemented interfaces provide.
*/
- private MethodCache createMethodCache(ConversionHandler conversionHandler)
+ private MethodCache createMethodCache(TypeConversionHandler
conversionHandler)
{
MethodCache methodCache = new MethodCache(log, conversionHandler);
//
@@ -231,7 +231,7 @@ public class ClassMap
/** Map of methods that are searchable according to method parameters
to find a match */
private final MethodMap methodMap;
- private MethodCache(Logger log, ConversionHandler conversionHandler)
+ private MethodCache(Logger log, TypeConversionHandler
conversionHandler)
{
this.log = log;
methodMap = new MethodMap(conversionHandler);
Modified:
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/ConversionHandler.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/ConversionHandler.java?rev=1854386&r1=1854385&r2=1854386&view=diff
==============================================================================
---
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/ConversionHandler.java
(original)
+++
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/ConversionHandler.java
Tue Feb 26 14:30:46 2019
@@ -27,13 +27,17 @@ package org.apache.velocity.util.introsp
*
* @author <a href="mailto:[email protected]">Claude Brisson</a>
* @version $Id: ConversionHandler.java $
+ * @deprecated use {@link TypeConversionHandler}
+ * @see TypeConversionHandler
* @since 2.0
*/
+@Deprecated
public interface ConversionHandler
{
/**
* Check to see if the conversion can be done using an explicit conversion
+ *
* @param formal expected formal type
* @param actual provided argument type
* @return null if no conversion is needed, or the appropriate Converter
object
@@ -55,10 +59,11 @@ public interface ConversionHandler
/**
* Add the given converter to the handler. Implementation should be
thread-safe.
*
- * @param formal expected formal type
- * @param actual provided argument type
+ * @param formal expected formal type
+ * @param actual provided argument type
* @param converter converter
* @since 2.0
*/
void addConverter(Class formal, Class actual, Converter converter);
}
+
Modified:
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/IntrospectionUtils.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/IntrospectionUtils.java?rev=1854386&r1=1854385&r2=1854386&view=diff
==============================================================================
---
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/IntrospectionUtils.java
(original)
+++
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/IntrospectionUtils.java
Tue Feb 26 14:30:46 2019
@@ -19,6 +19,14 @@ package org.apache.velocity.util.introsp
* under the License.
*/
+import org.apache.commons.lang3.reflect.TypeUtils;
+
+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;
+import java.lang.reflect.WildcardType;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@@ -66,7 +74,7 @@ public class IntrospectionUtils
* @param clazz input class
* @return boxed class
*/
- static Class getBoxedClass(Class clazz)
+ public static Class getBoxedClass(Class clazz)
{
Class boxed = boxingMap.get(clazz);
return boxed == null ? clazz : boxed;
@@ -77,16 +85,52 @@ public class IntrospectionUtils
* @param clazz input class
* @return unboxed class
*/
- static Class getUnboxedClass(Class clazz)
+ public static Class getUnboxedClass(Class clazz)
{
Class unboxed = unboxingMap.get(clazz);
return unboxed == null ? clazz : unboxed;
}
/**
- *
+ * returns the Class corresponding to a Type, if possible
+ * @param type the input Type
+ * @return found Class, if any
*/
-
+ public static Class getTypeClass(Type type)
+ {
+ if (type == null)
+ {
+ return null;
+ }
+ if (type instanceof Class)
+ {
+ return (Class)type;
+ }
+ else if (type instanceof ParameterizedType)
+ {
+ return (Class)((ParameterizedType)type).getRawType();
+ }
+ else if (type instanceof GenericArrayType)
+ {
+ Type componentType =
((GenericArrayType)type).getGenericComponentType();
+ Class componentClass = getTypeClass(componentType);
+ if (componentClass != null)
+ {
+ return Array.newInstance(componentClass, 0).getClass();
+ }
+ }
+ else if (type instanceof TypeVariable)
+ {
+ Type[] bounds = TypeUtils.getImplicitBounds((TypeVariable)type);
+ if (bounds.length == 1) return getTypeClass(bounds[0]);
+ }
+ else if (type instanceof WildcardType)
+ {
+ Type[] bounds =
TypeUtils.getImplicitUpperBounds((WildcardType)type);
+ if (bounds.length == 1) return getTypeClass(bounds[0]);
+ }
+ return null;
+ }
/**
* Determines whether a type represented by a class object is
@@ -108,92 +152,105 @@ public class IntrospectionUtils
* type or an object type of a primitive type that can be converted to
* the formal type.
*/
- public static boolean isMethodInvocationConvertible(Class formal,
+ public static boolean isMethodInvocationConvertible(Type formal,
Class actual,
boolean possibleVarArg)
{
- /* if it's a null, it means the arg was null */
- if (actual == null)
+ Class formalClass = getTypeClass(formal);
+ if (formalClass != null)
{
- return !formal.isPrimitive();
- }
+ /* if it's a null, it means the arg was null */
+ if (actual == null)
+ {
+ return !formalClass.isPrimitive();
+ }
- /* Check for identity or widening reference conversion */
- if (formal.isAssignableFrom(actual))
- {
- return true;
- }
+ /* Check for identity or widening reference conversion */
+ if (formalClass.isAssignableFrom(actual))
+ {
+ return true;
+ }
- /* 2.0: Since MethodMap's comparison functions now use this method
with potentially reversed arguments order,
- * actual can be a primitive type. */
+ /* 2.0: Since MethodMap's comparison functions now use this method
with potentially reversed arguments order,
+ * actual can be a primitive type. */
- /* Check for boxing */
- if (!formal.isPrimitive() && actual.isPrimitive())
- {
- Class boxed = boxingMap.get(actual);
- if (boxed != null && boxed == formal ||
formal.isAssignableFrom(boxed)) return true;
- }
+ /* Check for boxing */
+ if (!formalClass.isPrimitive() && actual.isPrimitive())
+ {
+ Class boxed = boxingMap.get(actual);
+ if (boxed != null && boxed == formalClass ||
formalClass.isAssignableFrom(boxed)) return true;
+ }
- if (formal.isPrimitive())
- {
- if (actual.isPrimitive())
+ if (formalClass.isPrimitive())
{
- /* check for widening primitive conversion */
- if (formal == Short.TYPE && actual == Byte.TYPE)
- return true;
- if (formal == Integer.TYPE && (
+ if (actual.isPrimitive())
+ {
+ /* check for widening primitive conversion */
+ if (formalClass == Short.TYPE && actual == Byte.TYPE)
+ return true;
+ if (formalClass == Integer.TYPE && (
actual == Byte.TYPE || actual == Short.TYPE))
- return true;
- if (formal == Long.TYPE && (
+ return true;
+ if (formalClass == Long.TYPE && (
actual == Byte.TYPE || actual == Short.TYPE || actual
== Integer.TYPE))
- return true;
- if (formal == Float.TYPE && (
+ return true;
+ if (formalClass == Float.TYPE && (
actual == Byte.TYPE || actual == Short.TYPE || actual
== Integer.TYPE ||
- actual == Long.TYPE))
- return true;
- if (formal == Double.TYPE && (
+ actual == Long.TYPE))
+ return true;
+ if (formalClass == Double.TYPE && (
actual == Byte.TYPE || actual == Short.TYPE || actual
== Integer.TYPE ||
- actual == Long.TYPE || actual == Float.TYPE))
- return true;
- }
- else
- {
- /* Check for unboxing with widening primitive conversion. */
- if (formal == Boolean.TYPE && actual == Boolean.class)
- return true;
- if (formal == Character.TYPE && actual == Character.class)
- return true;
- if (formal == Byte.TYPE && actual == Byte.class)
- return true;
- if (formal == Short.TYPE && (actual == Short.class || actual
== Byte.class))
- return true;
- if (formal == Integer.TYPE && (actual == Integer.class ||
actual == Short.class ||
+ actual == Long.TYPE || actual == Float.TYPE))
+ return true;
+ } else
+ {
+ /* Check for unboxing with widening primitive conversion.
*/
+ if (formalClass == Boolean.TYPE && actual == Boolean.class)
+ return true;
+ if (formalClass == Character.TYPE && actual ==
Character.class)
+ return true;
+ if (formalClass == Byte.TYPE && actual == Byte.class)
+ return true;
+ if (formalClass == Short.TYPE && (actual == Short.class ||
actual == Byte.class))
+ return true;
+ if (formalClass == Integer.TYPE && (actual ==
Integer.class || actual == Short.class ||
actual == Byte.class))
- return true;
- if (formal == Long.TYPE && (actual == Long.class || actual ==
Integer.class ||
+ return true;
+ if (formalClass == Long.TYPE && (actual == Long.class ||
actual == Integer.class ||
actual == Short.class || actual == Byte.class))
- return true;
- if (formal == Float.TYPE && (actual == Float.class || actual
== Long.class ||
+ return true;
+ if (formalClass == Float.TYPE && (actual == Float.class ||
actual == Long.class ||
actual == Integer.class || actual == Short.class ||
actual == Byte.class))
- return true;
- if (formal == Double.TYPE && (actual == Double.class || actual
== Float.class ||
+ return true;
+ if (formalClass == Double.TYPE && (actual == Double.class
|| actual == Float.class ||
actual == Long.class || actual == Integer.class ||
actual == Short.class ||
actual == Byte.class))
- return true;
+ return true;
+ }
}
- }
- /* Check for vararg conversion. */
- if (possibleVarArg && formal.isArray())
+ /* Check for vararg conversion. */
+ if (possibleVarArg && formalClass.isArray())
+ {
+ if (actual.isArray())
+ {
+ actual = actual.getComponentType();
+ }
+ return
isMethodInvocationConvertible(formalClass.getComponentType(),
+ actual, false);
+ }
+ return false;
+ }
+ else
{
- if (actual.isArray())
+ // no distinction between strict and implicit, not a big deal in
this case
+ if (TypeUtils.isAssignable(actual, formal))
{
- actual = actual.getComponentType();
+ return true;
}
- return isMethodInvocationConvertible(formal.getComponentType(),
- actual, false);
+ return possibleVarArg && TypeUtils.isArrayType(formal) &&
+ TypeUtils.isAssignable(actual,
TypeUtils.getArrayComponentType(formal));
}
- return false;
}
/**
@@ -212,55 +269,69 @@ public class IntrospectionUtils
* or formal and actual are both primitive types and actual can be
* subject to widening conversion to formal.
*/
- public static boolean isStrictMethodInvocationConvertible(Class formal,
+ public static boolean isStrictMethodInvocationConvertible(Type formal,
Class actual,
boolean
possibleVarArg)
{
- /* Check for nullity */
- if (actual == null)
+ Class formalClass = getTypeClass(formal);
+ if (formalClass != null)
{
- return !formal.isPrimitive();
- }
-
- /* Check for identity or widening reference conversion */
- if(formal.isAssignableFrom(actual))
- {
- return true;
- }
+ /* Check for nullity */
+ if (actual == null)
+ {
+ return !formalClass.isPrimitive();
+ }
- /* Check for widening primitive conversion. */
- if(formal.isPrimitive())
- {
- if(formal == Short.TYPE && (actual == Byte.TYPE))
- return true;
- if(formal == Integer.TYPE &&
- (actual == Short.TYPE || actual == Byte.TYPE))
- return true;
- if(formal == Long.TYPE &&
- (actual == Integer.TYPE || actual == Short.TYPE ||
- actual == Byte.TYPE))
- return true;
- if(formal == Float.TYPE &&
- (actual == Long.TYPE || actual == Integer.TYPE ||
- actual == Short.TYPE || actual == Byte.TYPE))
- return true;
- if(formal == Double.TYPE &&
- (actual == Float.TYPE || actual == Long.TYPE ||
- actual == Integer.TYPE || actual == Short.TYPE ||
- actual == Byte.TYPE))
+ /* Check for identity or widening reference conversion */
+ if (formalClass.isAssignableFrom(actual))
+ {
return true;
- }
+ }
- /* Check for vararg conversion. */
- if (possibleVarArg && formal.isArray())
+ /* Check for widening primitive conversion. */
+ if (formalClass.isPrimitive())
+ {
+ if (formal == Short.TYPE && (actual == Byte.TYPE))
+ return true;
+ if (formal == Integer.TYPE &&
+ (actual == Short.TYPE || actual == Byte.TYPE))
+ return true;
+ if (formal == Long.TYPE &&
+ (actual == Integer.TYPE || actual == Short.TYPE ||
+ actual == Byte.TYPE))
+ return true;
+ if (formal == Float.TYPE &&
+ (actual == Long.TYPE || actual == Integer.TYPE ||
+ actual == Short.TYPE || actual == Byte.TYPE))
+ return true;
+ if (formal == Double.TYPE &&
+ (actual == Float.TYPE || actual == Long.TYPE ||
+ actual == Integer.TYPE || actual == Short.TYPE ||
+ actual == Byte.TYPE))
+ return true;
+ }
+
+ /* Check for vararg conversion. */
+ if (possibleVarArg && formalClass.isArray())
+ {
+ if (actual.isArray())
+ {
+ actual = actual.getComponentType();
+ }
+ return
isStrictMethodInvocationConvertible(formalClass.getComponentType(),
+ actual, false);
+ }
+ return false;
+ }
+ else
{
- if (actual.isArray())
+ // no distinction between strict and implicit, not a big deal in
this case
+ if (TypeUtils.isAssignable(actual, formal))
{
- actual = actual.getComponentType();
+ return true;
}
- return
isStrictMethodInvocationConvertible(formal.getComponentType(),
- actual, false);
+ return possibleVarArg && TypeUtils.isArrayType(formal) &&
+ TypeUtils.isAssignable(actual,
TypeUtils.getArrayComponentType(formal));
}
- return false;
}
}
Modified:
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/Introspector.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/Introspector.java?rev=1854386&r1=1854385&r2=1854386&view=diff
==============================================================================
---
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/Introspector.java
(original)
+++
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/Introspector.java
Tue Feb 26 14:30:46 2019
@@ -68,7 +68,7 @@ public class Introspector extends Intros
* @param conversionHandler conversion handler
* @since 2.0
*/
- public Introspector(final Logger log, ConversionHandler conversionHandler)
+ public Introspector(final Logger log, TypeConversionHandler
conversionHandler)
{
super(log, conversionHandler);
}
Modified:
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/IntrospectorBase.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/IntrospectorBase.java?rev=1854386&r1=1854385&r2=1854386&view=diff
==============================================================================
---
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/IntrospectorBase.java
(original)
+++
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/IntrospectorBase.java
Tue Feb 26 14:30:46 2019
@@ -62,17 +62,13 @@ public abstract class IntrospectorBase
/** The Introspector Cache */
private final IntrospectorCache introspectorCache;
- /** The Conversion handler */
- private final ConversionHandler conversionHandler;
-
/**
* C'tor.
*/
- protected IntrospectorBase(final Logger log, final ConversionHandler
conversionHandler)
+ protected IntrospectorBase(final Logger log, final TypeConversionHandler
conversionHandler)
{
this.log = log;
introspectorCache = new IntrospectorCache(log, conversionHandler);
- this.conversionHandler = conversionHandler;
}
/**
Modified:
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/IntrospectorCache.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/IntrospectorCache.java?rev=1854386&r1=1854385&r2=1854386&view=diff
==============================================================================
---
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/IntrospectorCache.java
(original)
+++
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/IntrospectorCache.java
Tue Feb 26 14:30:46 2019
@@ -68,12 +68,12 @@ public final class IntrospectorCache
/**
* Conversion handler
*/
- private final ConversionHandler conversionHandler;
+ private final TypeConversionHandler conversionHandler;
/**
* C'tor
*/
- public IntrospectorCache(final Logger log, final ConversionHandler
conversionHandler)
+ public IntrospectorCache(final Logger log, final TypeConversionHandler
conversionHandler)
{
this.log = log;
this.conversionHandler = conversionHandler;
Modified:
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/MethodMap.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/MethodMap.java?rev=1854386&r1=1854385&r2=1854386&view=diff
==============================================================================
---
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/MethodMap.java
(original)
+++
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/MethodMap.java
Tue Feb 26 14:30:46 2019
@@ -19,9 +19,11 @@ package org.apache.velocity.util.introsp
* under the License.
*/
+import org.apache.commons.lang3.reflect.TypeUtils;
import org.apache.velocity.exception.VelocityException;
import java.lang.reflect.Method;
+import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
@@ -54,7 +56,7 @@ public class MethodMap
private static final int IMPLCITLY_CONVERTIBLE = 2;
private static final int STRICTLY_CONVERTIBLE = 3;
- ConversionHandler conversionHandler;
+ TypeConversionHandler conversionHandler;
/**
* Default constructor
@@ -69,7 +71,7 @@ public class MethodMap
* @param conversionHandler conversion handler
* @since 2.0
*/
- public MethodMap(ConversionHandler conversionHandler)
+ public MethodMap(TypeConversionHandler conversionHandler)
{
this.conversionHandler = conversionHandler;
}
@@ -173,7 +175,7 @@ public class MethodMap
Method method;
/* cache arguments classes array */
- Class[] methodTypes;
+ Type[] methodTypes;
/* specificity: how does the best match compare to provided arguments
* one one LESS_SPECIFIC, MORE_SPECIFIC or INCOMPARABLE */
@@ -190,9 +192,9 @@ public class MethodMap
{
this.method = method;
this.applicability = applicability;
- this.methodTypes = method.getParameterTypes();
+ this.methodTypes = method.getGenericParameterTypes();
this.specificity = compare(methodTypes, unboxedArgs);
- this.varargs = methodTypes.length > 0 &&
methodTypes[methodTypes.length - 1].isArray();
+ this.varargs = methodTypes.length > 0 &&
TypeUtils.isArrayType(methodTypes[methodTypes.length - 1]);
}
}
@@ -322,74 +324,74 @@ public class MethodMap
/**
* Determines which method signature (represented by a class array) is more
* specific. This defines a partial ordering on the method signatures.
- * @param c1 first signature to compare
- * @param c2 second signature to compare
+ * @param t1 first signature to compare
+ * @param t2 second signature to compare
* @return MORE_SPECIFIC if c1 is more specific than c2, LESS_SPECIFIC if
* c1 is less specific than c2, INCOMPARABLE if they are incomparable.
*/
- private int compare(Class[] c1, Class[] c2)
+ private int compare(Type[] t1, Type[] t2)
{
- boolean c1IsVararag = false;
- boolean c2IsVararag = false;
+ boolean t1IsVararag = false;
+ boolean t2IsVararag = false;
boolean fixedLengths = false;
// compare lengths to handle comparisons where the size of the arrays
// doesn't match, but the methods are both applicable due to the fact
// that one is a varargs method
- if (c1.length > c2.length)
+ if (t1.length > t2.length)
{
- int l2 = c2.length;
+ int l2 = t2.length;
if (l2 == 0)
{
return MORE_SPECIFIC;
}
- c2 = Arrays.copyOf(c2, c1.length);
- Class itemClass = c2[l2 - 1].getComponentType();
+ t2 = Arrays.copyOf(t2, t1.length);
+ Type itemType = TypeUtils.getArrayComponentType(t2[l2 - 1]);
/* if item class is null, then it implies the vaarg is #1
* (and receives an empty array)
*/
- if (itemClass == null)
+ if (itemType == null)
{
/* by construct, we have c1.length = l2 + 1 */
- c1IsVararag = true;
- c2[c1.length - 1] = null;
+ t1IsVararag = true;
+ t2[t1.length - 1] = null;
}
else
{
- c2IsVararag = true;
- for (int i = l2 - 1; i < c1.length; ++i)
+ t2IsVararag = true;
+ for (int i = l2 - 1; i < t1.length; ++i)
{
/* also overwrite the vaargs itself */
- c2[i] = itemClass;
+ t2[i] = itemType;
}
}
fixedLengths = true;
}
- else if (c2.length > c1.length)
+ else if (t2.length > t1.length)
{
- int l1 = c1.length;
+ int l1 = t1.length;
if (l1 == 0)
{
return LESS_SPECIFIC;
}
- c1 = Arrays.copyOf(c1, c2.length);
- Class itemClass = c1[l1 - 1].getComponentType();
+ t1 = Arrays.copyOf(t1, t2.length);
+ Type itemType = TypeUtils.getArrayComponentType(t1[l1 - 1]);
/* if item class is null, then it implies the vaarg is #2
* (and receives an empty array)
*/
- if (itemClass == null)
+ if (itemType == null)
{
/* by construct, we have c2.length = l1 + 1 */
- c2IsVararag = true;
- c1[c2.length - 1] = null;
+ t2IsVararag = true;
+ t1[t2.length - 1] = null;
}
else
{
- c1IsVararag = true;
- for (int i = l1 - 1; i < c2.length; ++i)
+ t1IsVararag = true;
+ for (int i = l1 - 1; i < t2.length; ++i)
{
/* also overwrite the vaargs itself */
- c1[i] = itemClass;
+ t1[i] = itemType;
}
}
fixedLengths = true;
@@ -398,52 +400,72 @@ public class MethodMap
/* ok, move on and compare those of equal lengths */
int fromC1toC2 = STRICTLY_CONVERTIBLE;
int fromC2toC1 = STRICTLY_CONVERTIBLE;
- for(int i = 0; i < c1.length; ++i)
+ for(int i = 0; i < t1.length; ++i)
{
- boolean last = !fixedLengths && (i == c1.length - 1);
- if (c1[i] != c2[i])
+ Class c1 = t1[i] == null ? null :
IntrospectionUtils.getTypeClass(t1[i]);
+ Class c2 = t2[i] == null ? null :
IntrospectionUtils.getTypeClass(t2[i]);
+ boolean last = !fixedLengths && (i == t1.length - 1);
+ if (t1[i] == null && t2[i] != null || t1[i] != null && t2[i] ==
null || !t1[i].equals(t2[i]))
{
- if (c1[i] == null)
+ if (t1[i] == null)
{
fromC2toC1 = NOT_CONVERTIBLE;
- if (c2[i].isPrimitive())
+ if (c2 != null && c2.isPrimitive())
{
fromC1toC2 = NOT_CONVERTIBLE;
}
}
- else if (c2[i] == null)
+ else if (t2[i] == null)
{
fromC1toC2 = NOT_CONVERTIBLE;
- if (c1[i].isPrimitive())
+ if (c1 != null && c1.isPrimitive())
{
fromC2toC1 = NOT_CONVERTIBLE;
}
}
else
{
- switch (fromC1toC2)
+ if (c1 != null)
{
- case STRICTLY_CONVERTIBLE:
- if (isStrictConvertible(c2[i], c1[i], last)) break;
- fromC1toC2 = IMPLCITLY_CONVERTIBLE;
- case IMPLCITLY_CONVERTIBLE:
- if (isConvertible(c2[i], c1[i], last)) break;
- fromC1toC2 = EXPLICITLY_CONVERTIBLE;
- case EXPLICITLY_CONVERTIBLE:
- if (isExplicitlyConvertible(c2[i], c1[i], last))
break;
- fromC1toC2 = NOT_CONVERTIBLE;
- }
- switch (fromC2toC1)
- {
- case STRICTLY_CONVERTIBLE:
- if (isStrictConvertible(c1[i], c2[i], last)) break;
- fromC2toC1 = IMPLCITLY_CONVERTIBLE;
- case IMPLCITLY_CONVERTIBLE:
- if (isConvertible(c1[i], c2[i], last)) break;
- fromC2toC1 = EXPLICITLY_CONVERTIBLE;
- case EXPLICITLY_CONVERTIBLE:
- if (isExplicitlyConvertible(c1[i], c2[i], last))
break;
- fromC2toC1 = NOT_CONVERTIBLE;
+ switch (fromC1toC2)
+ {
+ case STRICTLY_CONVERTIBLE:
+ if (isStrictConvertible(t2[i], c1, last))
break;
+ fromC1toC2 = IMPLCITLY_CONVERTIBLE;
+ case IMPLCITLY_CONVERTIBLE:
+ if (isConvertible(t2[i], c1, last)) break;
+ fromC1toC2 = EXPLICITLY_CONVERTIBLE;
+ case EXPLICITLY_CONVERTIBLE:
+ if (isExplicitlyConvertible(t2[i], c1, last))
break;
+ fromC1toC2 = NOT_CONVERTIBLE;
+ }
+ }
+ else if (fromC1toC2 > NOT_CONVERTIBLE)
+ {
+ fromC1toC2 = TypeUtils.isAssignable(t1[i], t2[i]) ?
+ Math.min(fromC1toC2, IMPLCITLY_CONVERTIBLE) :
+ NOT_CONVERTIBLE;
+ }
+ if (c2 != null)
+ {
+ switch (fromC2toC1)
+ {
+ case STRICTLY_CONVERTIBLE:
+ if (isStrictConvertible(t1[i], c2, last))
break;
+ fromC2toC1 = IMPLCITLY_CONVERTIBLE;
+ case IMPLCITLY_CONVERTIBLE:
+ if (isConvertible(t1[i], c2, last)) break;
+ fromC2toC1 = EXPLICITLY_CONVERTIBLE;
+ case EXPLICITLY_CONVERTIBLE:
+ if (isExplicitlyConvertible(t1[i], c2, last))
break;
+ fromC2toC1 = NOT_CONVERTIBLE;
+ }
+ }
+ else if (fromC2toC1 > NOT_CONVERTIBLE)
+ {
+ fromC2toC1 = TypeUtils.isAssignable(t2[i], t1[i]) ?
+ Math.min(fromC2toC1, IMPLCITLY_CONVERTIBLE) :
+ NOT_CONVERTIBLE;
}
}
}
@@ -472,8 +494,8 @@ public class MethodMap
* If one method accepts varargs and the other does not,
* call the non-vararg one more specific.
*/
- boolean last1Array = c1IsVararag || !fixedLengths && c1[c1.length
- 1].isArray();
- boolean last2Array = c2IsVararag || !fixedLengths && c2[c2.length
- 1].isArray();
+ boolean last1Array = t1IsVararag || !fixedLengths &&
TypeUtils.isArrayType (t1[t1.length - 1]);
+ boolean last2Array = t2IsVararag || !fixedLengths &&
TypeUtils.isArrayType(t2[t2.length - 1]);
if (last1Array && !last2Array)
{
return LESS_SPECIFIC;
@@ -499,14 +521,13 @@ public class MethodMap
*/
private int getApplicability(Method method, Class[] classes)
{
- Class[] methodArgs = method.getParameterTypes();
+ Type[] methodArgs = method.getGenericParameterTypes();
int ret = STRICTLY_CONVERTIBLE;
if (methodArgs.length > classes.length)
{
// if there's just one more methodArg than class arg
// and the last methodArg is an array, then treat it as a vararg
- if (methodArgs.length == classes.length + 1 &&
- methodArgs[methodArgs.length - 1].isArray())
+ if (methodArgs.length == classes.length + 1 &&
TypeUtils.isArrayType(methodArgs[methodArgs.length - 1]))
{
// all the args preceding the vararg must match
for (int i = 0; i < classes.length; i++)
@@ -541,13 +562,14 @@ public class MethodMap
// (e.g. String when the method is expecting String...)
for(int i = 0; i < classes.length; ++i)
{
- if (!isStrictConvertible(methodArgs[i], classes[i], i ==
classes.length - 1 && methodArgs[i].isArray()))
+ boolean possibleVararg = i == classes.length - 1 &&
TypeUtils.isArrayType(methodArgs[i]);
+ if (!isStrictConvertible(methodArgs[i], classes[i],
possibleVararg))
{
- if (isConvertible(methodArgs[i], classes[i], i ==
classes.length - 1 && methodArgs[i].isArray()))
+ if (isConvertible(methodArgs[i], classes[i],
possibleVararg))
{
ret = Math.min(ret, IMPLCITLY_CONVERTIBLE);
}
- else if (isExplicitlyConvertible(methodArgs[i],
classes[i], i == classes.length - 1 && methodArgs[i].isArray()))
+ else if (isExplicitlyConvertible(methodArgs[i],
classes[i], possibleVararg))
{
ret = Math.min(ret, EXPLICITLY_CONVERTIBLE);
}
@@ -562,8 +584,8 @@ public class MethodMap
else if (methodArgs.length > 0) // more arguments given than the
method accepts; check for varargs
{
// check that the last methodArg is an array
- Class lastarg = methodArgs[methodArgs.length - 1];
- if (!lastarg.isArray())
+ Type lastarg = methodArgs[methodArgs.length - 1];
+ if (!TypeUtils.isArrayType(lastarg))
{
return NOT_CONVERTIBLE;
}
@@ -589,7 +611,7 @@ public class MethodMap
}
// check that all remaining arguments are convertible to the
vararg type
- Class vararg = lastarg.getComponentType();
+ Type vararg = TypeUtils.getArrayComponentType(lastarg);
for (int i = methodArgs.length - 1; i < classes.length; ++i)
{
if (!isStrictConvertible(vararg, classes[i], false))
@@ -621,7 +643,7 @@ public class MethodMap
* @param possibleVarArg
* @return convertible
*/
- private boolean isConvertible(Class formal, Class actual, boolean
possibleVarArg)
+ private boolean isConvertible(Type formal, Class actual, boolean
possibleVarArg)
{
return IntrospectionUtils.
isMethodInvocationConvertible(formal, actual, possibleVarArg);
@@ -636,7 +658,7 @@ public class MethodMap
* @param possibleVarArg
* @return convertible
*/
- private static boolean isStrictConvertible(Class formal, Class actual,
boolean possibleVarArg)
+ private static boolean isStrictConvertible(Type formal, Class actual,
boolean possibleVarArg)
{
return IntrospectionUtils.
isStrictMethodInvocationConvertible(formal, actual,
possibleVarArg);
@@ -650,7 +672,7 @@ public class MethodMap
* @param possibleVarArg
* @return
*/
- private boolean isExplicitlyConvertible(Class formal, Class actual,
boolean possibleVarArg)
+ private boolean isExplicitlyConvertible(Type formal, Class actual, boolean
possibleVarArg)
{
return conversionHandler != null &&
conversionHandler.isExplicitlyConvertible(formal, actual, possibleVarArg);
}
Copied:
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/TypeConversionHandlerImpl.java
(from r1854372,
velocity/engine/branches/VELOCITY-892/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/TypeConversionHandlerImpl.java)
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/TypeConversionHandlerImpl.java?p2=velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/TypeConversionHandlerImpl.java&p1=velocity/engine/branches/VELOCITY-892/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/TypeConversionHandlerImpl.java&r1=1854372&r2=1854386&rev=1854386&view=diff
==============================================================================
---
velocity/engine/branches/VELOCITY-892/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/TypeConversionHandlerImpl.java
(original)
+++
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/TypeConversionHandlerImpl.java
Tue Feb 26 14:30:46 2019
@@ -19,11 +19,13 @@ package org.apache.velocity.util.introsp
* under the License.
*/
+import org.apache.commons.lang3.LocaleUtils;
import org.apache.commons.lang3.reflect.TypeUtils;
import org.apache.commons.lang3.tuple.Pair;
import java.lang.reflect.Type;
import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -89,6 +91,7 @@ public class TypeConversionHandlerImpl i
static final String NUMBER_CLASS = "java.lang.Number";
static final String CHARACTER_CLASS = "java.lang.Character";
static final String STRING_CLASS = "java.lang.String";
+ static final String LOCALE_CLASS = "java.util.Locale";
static
{
@@ -512,6 +515,17 @@ public class TypeConversionHandlerImpl i
return String.valueOf(o);
}
};
+
+ /* string to locale */
+ Converter<Locale> stringToLocale = new Converter<Locale>()
+ {
+ @Override
+ public Locale convert(Object o)
+ {
+ return o == null ? null : LocaleUtils.toLocale((String)o);
+ }
+ };
+ standardConverterMap.put(Pair.of(LOCALE_CLASS, STRING_CLASS),
stringToLocale);
}
/**
Modified:
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/UberspectImpl.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/UberspectImpl.java?rev=1854386&r1=1854385&r2=1854386&view=diff
==============================================================================
---
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/UberspectImpl.java
(original)
+++
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/UberspectImpl.java
Tue Feb 26 14:30:46 2019
@@ -19,6 +19,7 @@ package org.apache.velocity.util.introsp
* under the License.
*/
+import org.apache.commons.lang3.Conversion;
import org.apache.velocity.exception.VelocityException;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.RuntimeServices;
@@ -42,6 +43,7 @@ import org.slf4j.Logger;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.lang.reflect.Type;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
@@ -69,7 +71,7 @@ public class UberspectImpl implements Ub
/**
* the conversion handler
*/
- protected ConversionHandler conversionHandler;
+ protected TypeConversionHandler conversionHandler;
/**
* runtime services
@@ -86,7 +88,7 @@ public class UberspectImpl implements Ub
introspector = new Introspector(log, conversionHandler);
}
- public ConversionHandler getConversionHandler()
+ public TypeConversionHandler getConversionHandler()
{
return conversionHandler;
}
@@ -95,51 +97,86 @@ public class UberspectImpl implements Ub
* sets the runtime services
* @param rs runtime services
*/
+ @SuppressWarnings("deprecation")
public void setRuntimeServices(RuntimeServices rs)
{
rsvc = rs;
log = rsvc.getLog("introspection");
- String conversionHandlerClass =
rs.getString(RuntimeConstants.CONVERSION_HANDLER_CLASS);
- if (conversionHandlerClass == null ||
conversionHandlerClass.equals("none"))
+ Object conversionHandlerInstance =
rs.getProperty(RuntimeConstants.CONVERSION_HANDLER_INSTANCE);
+ if (conversionHandlerInstance == null)
{
- conversionHandler = null;
- }
- else
- {
- Object o = null;
-
- try
+ String conversionHandlerClass =
rs.getString(RuntimeConstants.CONVERSION_HANDLER_CLASS);
+ if (conversionHandlerClass != null &&
!conversionHandlerClass.equals("none"))
{
- o = ClassUtils.getNewInstance(conversionHandlerClass);
- }
- catch (ClassNotFoundException cnfe )
- {
- String err = "The specified class for ConversionHandler (" +
conversionHandlerClass
+ try
+ {
+ conversionHandlerInstance =
ClassUtils.getNewInstance(conversionHandlerClass);
+ }
+ catch (ClassNotFoundException cnfe )
+ {
+ String err = "The specified class for ConversionHandler ("
+ conversionHandlerClass
+ ") does not exist or is not accessible to the
current classloader.";
- log.error(err);
- throw new VelocityException(err, cnfe);
- }
- catch (InstantiationException ie)
- {
- throw new VelocityException("Could not instantiate class '" +
conversionHandlerClass + "'", ie);
+ log.error(err);
+ throw new VelocityException(err, cnfe);
+ }
+ catch (InstantiationException ie)
+ {
+ throw new VelocityException("Could not instantiate class
'" + conversionHandlerClass + "'", ie);
+ }
+ catch (IllegalAccessException ae)
+ {
+ throw new VelocityException("Cannot access class '" +
conversionHandlerClass + "'", ae);
+ }
}
- catch (IllegalAccessException ae)
+ }
+
+ if (conversionHandlerInstance != null)
+ {
+ if (conversionHandlerInstance instanceof ConversionHandler)
{
- throw new VelocityException("Cannot access class '" +
conversionHandlerClass + "'", ae);
- }
+ log.warn("The ConversionHandler interface is deprecated - see
the TypeConversionHandler interface");
+ final ConversionHandler ch =
(ConversionHandler)conversionHandlerInstance;
+ conversionHandler = new TypeConversionHandler()
+ {
+ @Override
+ public boolean isExplicitlyConvertible(Type formal, Class
actual, boolean possibleVarArg)
+ {
+ Class formalClass =
IntrospectionUtils.getTypeClass(formal);
+ if (formalClass != null) return
ch.isExplicitlyConvertible(formalClass, actual, possibleVarArg);
+ else return false;
+ }
- if (!(o instanceof ConversionHandler))
+ @Override
+ public Converter getNeededConverter(Type formal, Class
actual)
+ {
+ Class formalClass =
IntrospectionUtils.getTypeClass(formal);
+ if (formalClass != null) return
ch.getNeededConverter(formalClass, actual);
+ else return null;
+ }
+
+ @Override
+ public void addConverter(Type formal, Class actual,
Converter converter)
+ {
+ Class formalClass =
IntrospectionUtils.getTypeClass(formal);
+ if (formalClass != null) ch.addConverter(formalClass,
actual, converter);
+ else throw new UnsupportedOperationException("This
conversion handler doesn't know how to handle Type: " + formal.getTypeName());
+ }
+ };
+ }
+ else if (!(conversionHandlerInstance instanceof
TypeConversionHandler))
{
- String err = "The specified class for ResourceManager (" +
conversionHandlerClass
- + ") does not implement " +
ConversionHandler.class.getName()
+ String err = "The specified class or provided instance for the
conversion handler (" + conversionHandlerInstance.getClass().getName()
+ + ") does not implement " +
TypeConversionHandler.class.getName()
+ "; Velocity is not initialized correctly.";
log.error(err);
throw new VelocityException(err);
}
-
- conversionHandler = (ConversionHandler) o;
+ else
+ {
+ conversionHandler =
(TypeConversionHandler)conversionHandlerInstance;
+ }
}
}
@@ -256,7 +293,7 @@ public class UberspectImpl implements Ub
Method m = introspector.getMethod(obj.getClass(), methodName, args);
if (m != null)
{
- return new VelMethodImpl(m, false,
getNeededConverters(m.getParameterTypes(), args));
+ return new VelMethodImpl(m, false,
getNeededConverters(m.getGenericParameterTypes(), args));
}
Class cls = obj.getClass();
@@ -269,7 +306,7 @@ public class UberspectImpl implements Ub
{
// and create a method that knows to wrap the value
// before invoking the method
- return new VelMethodImpl(m, true,
getNeededConverters(m.getParameterTypes(), args));
+ return new VelMethodImpl(m, true,
getNeededConverters(m.getGenericParameterTypes(), args));
}
}
// watch for classes, to allow calling their static methods
(VELOCITY-102)
@@ -278,7 +315,7 @@ public class UberspectImpl implements Ub
m = introspector.getMethod((Class)obj, methodName, args);
if (m != null)
{
- return new VelMethodImpl(m, false,
getNeededConverters(m.getParameterTypes(), args));
+ return new VelMethodImpl(m, false,
getNeededConverters(m.getGenericParameterTypes(), args));
}
}
return null;
@@ -288,7 +325,7 @@ public class UberspectImpl implements Ub
* get the list of needed converters to adapt passed argument types to
method types
* @return null if not conversion needed, otherwise an array containing
needed converters
*/
- private Converter[] getNeededConverters(Class[] expected, Object[]
provided)
+ private Converter[] getNeededConverters(Type[] expected, Object[] provided)
{
if (conversionHandler == null) return null;
// var args are not handled here - CB TODO
Modified:
velocity/engine/trunk/velocity-engine-core/src/main/resources/org/apache/velocity/runtime/defaults/velocity.properties
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/resources/org/apache/velocity/runtime/defaults/velocity.properties?rev=1854386&r1=1854385&r2=1854386&view=diff
==============================================================================
---
velocity/engine/trunk/velocity-engine-core/src/main/resources/org/apache/velocity/runtime/defaults/velocity.properties
(original)
+++
velocity/engine/trunk/velocity-engine-core/src/main/resources/org/apache/velocity/runtime/defaults/velocity.properties
Tue Feb 26 14:30:46 2019
@@ -210,7 +210,7 @@ runtime.introspector.uberspect = org.apa
# Sets the data types Conversion Handler used by the default uberspector
# ----------------------------------------------------------------------------
-runtime.conversion.handler.class =
org.apache.velocity.util.introspection.ConversionHandlerImpl
+runtime.conversion.handler.class =
org.apache.velocity.util.introspection.TypeConversionHandlerImpl
# ----------------------------------------------------------------------------
Propchange: velocity/engine/trunk/velocity-engine-core/src/test/java/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Feb 26 14:30:46 2019
@@ -1,5 +1,6 @@
/velocity/engine/branches/2.0_Exp/src/test:991639-992140
/velocity/engine/branches/2.0_Exp/velocity-engine-core/src/test/java:958513,991637-995742
+/velocity/engine/branches/VELOCITY-892/velocity-engine-core/src/test/java:1844076-1854372
/velocity/engine/branches/VELOCITY-898/velocity-engine-core/src/test/java:1843220-1843786
/velocity/engine/trunk/src/test:1032134
/velocity/engine/trunk/velocity-engine-core/src/test/java:992133,1032159
Modified:
velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/util/introspection/ConversionHandlerTestCase.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/util/introspection/ConversionHandlerTestCase.java?rev=1854386&r1=1854385&r2=1854386&view=diff
==============================================================================
---
velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/util/introspection/ConversionHandlerTestCase.java
(original)
+++
velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/util/introspection/ConversionHandlerTestCase.java
Tue Feb 26 14:30:46 2019
@@ -19,6 +19,8 @@
package org.apache.velocity.test.util.introspection;
import junit.framework.TestSuite;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.reflect.TypeUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
@@ -28,11 +30,11 @@ import org.apache.velocity.context.Conte
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.RuntimeInstance;
import org.apache.velocity.test.BaseTestCase;
-import org.apache.velocity.util.introspection.ConversionHandler;
-import org.apache.velocity.util.introspection.ConversionHandlerImpl;
import org.apache.velocity.util.introspection.Converter;
import org.apache.velocity.util.introspection.Info;
import org.apache.velocity.util.introspection.IntrospectionUtils;
+import org.apache.velocity.util.introspection.TypeConversionHandler;
+import org.apache.velocity.util.introspection.TypeConversionHandlerImpl;
import org.apache.velocity.util.introspection.Uberspect;
import org.apache.velocity.util.introspection.UberspectImpl;
@@ -41,6 +43,9 @@ import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
@@ -114,7 +119,7 @@ public class ConversionHandlerTestCase e
Uberspect uberspect = ve.getUberspect();
assertTrue(uberspect instanceof UberspectImpl);
UberspectImpl ui = (UberspectImpl)uberspect;
- ConversionHandler ch = ui.getConversionHandler();
+ TypeConversionHandler ch = ui.getConversionHandler();
assertTrue(ch != null);
ch.addConverter(Float.class, Obj.class, new Converter<Float>()
{
@@ -124,11 +129,87 @@ public class ConversionHandlerTestCase e
return 4.5f;
}
});
+ ch.addConverter(TypeUtils.parameterize(List.class, Integer.class),
String.class, new Converter<List<Integer>>()
+ {
+ @Override
+ public List<Integer> convert(Object o)
+ {
+ return Arrays.<Integer>asList(1,2,3);
+ }
+ });
+ ch.addConverter(TypeUtils.parameterize(List.class, String.class),
String.class, new Converter<List<String>>()
+ {
+ @Override
+ public List<String> convert(Object o)
+ {
+ return Arrays.<String>asList("a", "b", "c");
+ }
+ });
VelocityContext context = new VelocityContext();
context.put("obj", new Obj());
Writer writer = new StringWriter();
ve.evaluate(context, writer, "test", "$obj.integralFloat($obj) /
$obj.objectFloat($obj)");
assertEquals("float ok: 4.5 / Float ok: 4.5", writer.toString());
+ writer = new StringWriter();
+ ve.evaluate(context, writer, "test",
"$obj.iWantAStringList('anything')");
+ assertEquals("correct", writer.toString());
+ writer = new StringWriter();
+ ve.evaluate(context, writer, "test",
"$obj.iWantAnIntegerList('anything')");
+ assertEquals("correct", writer.toString());
+ }
+
+ /* converts *everything* to string "foo" */
+ public static class MyCustomConverter implements TypeConversionHandler
+ {
+ Converter<String> myCustomConverter = new Converter<String>()
+ {
+
+ @Override
+ public String convert(Object o)
+ {
+ return "foo";
+ }
+ };
+
+ @Override
+ public boolean isExplicitlyConvertible(Type formal, Class actual,
boolean possibleVarArg)
+ {
+ return true;
+ }
+
+ @Override
+ public Converter getNeededConverter(Type formal, Class actual)
+ {
+ return myCustomConverter;
+ }
+
+ @Override
+ public void addConverter(Type formal, Class actual, Converter
converter)
+ {
+ throw new RuntimeException("not implemented");
+ }
+ }
+
+ public void testCustomConversionHandlerInstance()
+ {
+ RuntimeInstance ve = new RuntimeInstance();
+ ve.setProperty( Velocity.VM_PERM_INLINE_LOCAL, Boolean.TRUE);
+ ve.setProperty(Velocity.RUNTIME_LOG_INSTANCE, log);
+ ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "file");
+ ve.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH,
TEST_COMPARE_DIR + "/conversion");
+ ve.setProperty(RuntimeConstants.CONVERSION_HANDLER_INSTANCE, new
MyCustomConverter());
+ ve.init();
+ Uberspect uberspect = ve.getUberspect();
+ assertTrue(uberspect instanceof UberspectImpl);
+ UberspectImpl ui = (UberspectImpl)uberspect;
+ TypeConversionHandler ch = ui.getConversionHandler();
+ assertTrue(ch != null);
+ assertTrue(ch instanceof MyCustomConverter);
+ VelocityContext context = new VelocityContext();
+ context.put("obj", new Obj());
+ Writer writer = new StringWriter();
+ ve.evaluate(context, writer, "test", "$obj.objectString(1.0)");
+ assertEquals("String ok: foo", writer.toString());
}
/**
@@ -174,6 +255,15 @@ public class ConversionHandlerTestCase e
}
}
+ public void testOtherConversions() throws Exception
+ {
+ VelocityEngine ve = createEngine(false);
+ VelocityContext context = createContext();
+ StringWriter writer = new StringWriter();
+ ve.evaluate(context, writer,"test", "$strings.join(['foo', 'bar'],
',')");
+ assertEquals("foo,bar", writer.toString());
+ }
+
/**
* Return and initialize engine
* @return
@@ -264,6 +354,7 @@ public class ConversionHandlerTestCase e
};
context.put("types", types);
context.put("introspect", new Introspect());
+ context.put("strings", new StringUtils());
return context;
}
@@ -294,14 +385,28 @@ public class ConversionHandlerTestCase e
public String locale(Locale loc) { return "Locale ok: " + loc; }
public String toString() { return "instance of Obj"; }
+
+ public String iWantAStringList(List<String> list)
+ {
+ if (list != null && list.size() == 3 && list.get(0).equals("a") &&
list.get(1).equals("b") && list.get(2).equals("c"))
+ return "correct";
+ else return "wrong";
+ }
+
+ public String iWantAnIntegerList(List<Integer> list)
+ {
+ if (list != null && list.size() == 3 && list.get(0).equals(1) &&
list.get(1).equals(2) && list.get(2).equals(3))
+ return "correct";
+ else return "wrong";
+ }
}
public static class Introspect
{
- private ConversionHandler handler;
+ private TypeConversionHandler handler;
public Introspect()
{
- handler = new ConversionHandlerImpl();
+ handler = new TypeConversionHandlerImpl();
}
public boolean isStrictlyConvertible(Class expected, Class provided)
{