Author: henrib
Date: Wed Aug 24 15:11:15 2011
New Revision: 1161143
URL: http://svn.apache.org/viewvc?rev=1161143&view=rev
Log:
Constructors wrapping in JexlMethod;
Allows to cache during interpretation and overload discovery related to
constructor in Uberspect (for instance, using factories)
Modified:
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlEngine.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/introspection/Uberspect.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/introspection/UberspectImpl.java
Modified:
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java
URL:
http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java?rev=1161143&r1=1161142&r2=1161143&view=diff
==============================================================================
---
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java
(original)
+++
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java
Wed Aug 24 15:11:15 2011
@@ -16,7 +16,6 @@
*/
package org.apache.commons.jexl2;
-import java.lang.reflect.Constructor;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
@@ -335,10 +334,10 @@ public class Interpreter implements Pars
// allow namespace to be instantiated as functor with context if
possible, not an error otherwise
if (namespace instanceof Class<?>) {
Object[] args = new Object[]{context};
- Constructor<?> ctor = uberspect.getConstructor(namespace, args,
node);
+ JexlMethod ctor = uberspect.getConstructor(namespace, args, node);
if (ctor != null) {
try {
- namespace = ctor.newInstance(args);
+ namespace = ctor.invoke(namespace, args);
if (functors == null) {
functors = new HashMap<String, Object>();
}
@@ -416,10 +415,9 @@ public class Interpreter implements Pars
/** {@inheritDoc} */
public Object visit(ASTArrayAccess node, Object data) {
- // first objectNode is the identifier
+ // first objectNode is the identifier
Object object = node.jjtGetChild(0).jjtAccept(this, data);
- // can have multiple nodes - either an expression, integer literal or
- // reference
+ // can have multiple nodes - either an expression, integer literal or
reference
int numChildren = node.jjtGetNumChildren();
for (int i = 1; i < numChildren; i++) {
JexlNode nindex = node.jjtGetChild(i);
@@ -855,7 +853,7 @@ public class Interpreter implements Pars
int n = 0;
try {
Object result = null;
- /* first objectNode is the expression */
+ /* first objectNode is the condition */
Object expression = node.jjtGetChild(0).jjtAccept(this, data);
if (arithmetic.toBoolean(expression)) {
// first objectNode is true statement
@@ -1012,7 +1010,8 @@ public class Interpreter implements Pars
}
}
if (xjexl == null) {
- Object eval = vm.invoke(bean, argv); // vm cannot be null if
xjexl is null
+ // vm cannot be null if xjexl is null
+ Object eval = vm.invoke(bean, argv);
// cache executor in volatile JexlNode.value
if (cacheable && vm.isCacheable()) {
node.jjtSetValue(vm);
@@ -1072,10 +1071,20 @@ public class Interpreter implements Pars
}
JexlException xjexl = null;
- try {
- Constructor<?> ctor = uberspect.getConstructor(cobject, argv,
node);
- // DG: If we can't find an exact match, narrow the parameters and
- // try again!
+ try {
+ // attempt to reuse last constructor cached in volatile
JexlNode.value
+ if (cache) {
+ Object cached = node.jjtGetValue();
+ if (cached instanceof JexlMethod) {
+ JexlMethod mctor = (JexlMethod) cached;
+ Object eval = mctor.tryInvoke(null, cobject, argv);
+ if (!mctor.tryFailed(eval)) {
+ return eval;
+ }
+ }
+ }
+ JexlMethod ctor = uberspect.getConstructor(cobject, argv, node);
+ // DG: If we can't find an exact match, narrow the parameters and
try again
if (ctor == null) {
if (arithmetic.narrowArguments(argv)) {
ctor = uberspect.getConstructor(cobject, argv, node);
@@ -1085,7 +1094,12 @@ public class Interpreter implements Pars
}
}
if (xjexl == null) {
- return ctor.newInstance(argv);
+ Object instance = ctor.invoke(cobject, argv);
+ // cache executor in volatile JexlNode.value
+ if (cache && ctor.isCacheable()) {
+ node.jjtSetValue(ctor);
+ }
+ return instance;
}
} catch (InvocationTargetException e) {
xjexl = new JexlException(node, "constructor invocation error",
e.getCause());
Modified:
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlEngine.java
URL:
http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlEngine.java?rev=1161143&r1=1161142&r2=1161143&view=diff
==============================================================================
---
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlEngine.java
(original)
+++
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlEngine.java
Wed Aug 24 15:11:15 2011
@@ -26,7 +26,6 @@ import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
import java.lang.ref.SoftReference;
-import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Map;
import java.util.Set;
@@ -725,12 +724,12 @@ public class JexlEngine {
Object result = null;
JexlInfo info = debugInfo();
try {
- Constructor<?> ctor = uberspect.getConstructor(clazz, args, info);
+ JexlMethod ctor = uberspect.getConstructor(clazz, args, info);
if (ctor == null && arithmetic.narrowArguments(args)) {
ctor = uberspect.getConstructor(clazz, args, info);
}
if (ctor != null) {
- result = ctor.newInstance(args);
+ result = ctor.invoke(clazz, args);
} else {
xjexl = new JexlException(info, "failed finding constructor
for " + clazz.toString());
}
Modified:
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/introspection/Uberspect.java
URL:
http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/introspection/Uberspect.java?rev=1161143&r1=1161142&r2=1161143&view=diff
==============================================================================
---
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/introspection/Uberspect.java
(original)
+++
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/introspection/Uberspect.java
Wed Aug 24 15:11:15 2011
@@ -18,7 +18,6 @@
package org.apache.commons.jexl2.introspection;
import java.util.Iterator;
-import java.lang.reflect.Constructor;
import org.apache.commons.jexl2.JexlInfo;
/**
@@ -41,7 +40,7 @@ public interface Uberspect {
* @param info contextual information
* @return a {@link Constructor}
*/
- Constructor<?> getConstructor(Object ctorHandle, Object[] args, JexlInfo
info);
+ JexlMethod getConstructor(Object ctorHandle, Object[] args, JexlInfo info);
/**
* Returns a JexlMethod.
* @param obj the object
Modified:
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/introspection/UberspectImpl.java
URL:
http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/introspection/UberspectImpl.java?rev=1161143&r1=1161142&r2=1161143&view=diff
==============================================================================
---
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/introspection/UberspectImpl.java
(original)
+++
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/introspection/UberspectImpl.java
Wed Aug 24 15:11:15 2011
@@ -20,10 +20,12 @@ import org.apache.commons.jexl2.internal
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
+import java.lang.reflect.InvocationTargetException;
+
import java.util.Enumeration;
import java.util.Iterator;
-
import java.util.Map;
+
import org.apache.commons.jexl2.JexlInfo;
import org.apache.commons.jexl2.JexlException;
import org.apache.commons.jexl2.internal.AbstractExecutor;
@@ -44,7 +46,7 @@ public class UberspectImpl extends Intro
* Publicly exposed special failure object returned by tryInvoke.
*/
public static final Object TRY_FAILED = AbstractExecutor.TRY_FAILED;
-
+
/**
* Creates a new UberspectImpl.
* @param runtimeLogger the logger used for all logging needs
@@ -52,7 +54,7 @@ public class UberspectImpl extends Intro
public UberspectImpl(Log runtimeLogger) {
super(runtimeLogger);
}
-
+
/**
* Resets this Uberspect class loader.
* @param cloader the class loader to use
@@ -72,8 +74,8 @@ public class UberspectImpl extends Intro
if (obj.getClass().isArray()) {
return new ArrayIterator(obj);
}
- if (obj instanceof Map<?,?>) {
- return ((Map<?,?>) obj).values().iterator();
+ if (obj instanceof Map<?, ?>) {
+ return ((Map<?, ?>) obj).values().iterator();
}
if (obj instanceof Enumeration<?>) {
return new EnumerationIterator<Object>((Enumeration<Object>) obj);
@@ -89,7 +91,7 @@ public class UberspectImpl extends Intro
if (it != null &&
Iterator.class.isAssignableFrom(it.getReturnType())) {
return (Iterator<Object>) it.execute(obj, null);
}
- } catch(Exception xany) {
+ } catch (Exception xany) {
throw new JexlException(info, "unable to generate iterator()",
xany);
}
return null;
@@ -102,7 +104,7 @@ public class UberspectImpl extends Intro
* @param info debug info
* @return a {@link Field}.
*/
- public Field getField(Object obj, String name, JexlInfo info) {
+ protected Field getField(Object obj, String name, JexlInfo info) {
final Class<?> clazz = obj instanceof Class<?> ? (Class<?>) obj :
obj.getClass();
return getField(clazz, name);
}
@@ -110,8 +112,67 @@ public class UberspectImpl extends Intro
/**
* {@inheritDoc}
*/
- public Constructor<?> getConstructor(Object ctorHandle, Object[] args,
JexlInfo info) {
- return getConstructor(ctorHandle, args);
+ public JexlMethod getConstructor(Object ctorHandle, Object[] args,
JexlInfo info) {
+ final Constructor<?> ctor = getConstructor(ctorHandle, args);
+ if (ctor != null) {
+ JexlMethod jctor = new JexlMethod() {
+ public Object invoke(Object obj, Object[] params) throws
Exception {
+ Class<?> clazz = null;
+ if (obj instanceof Class<?>) {
+ clazz = (Class<?>) obj;
+ } else if (obj != null) {
+ clazz = base().getClassByName(obj.toString());
+ } else {
+ clazz = ctor.getDeclaringClass();
+ }
+ if (clazz.equals(ctor.getDeclaringClass())) {
+ return ctor.newInstance(params);
+ } else {
+ return null;
+ }
+ }
+
+ public Object tryInvoke(String name, Object obj, Object[]
params) {
+ Class<?> clazz = null;
+ if (obj instanceof Class<?>) {
+ clazz = (Class<?>) obj;
+ } else if (obj != null) {
+ clazz = base().getClassByName(obj.toString());
+ } else {
+ clazz = ctor.getDeclaringClass();
+ }
+ if (clazz.equals(ctor.getDeclaringClass())
+ && (name == null || name.equals(clazz.getName()))) {
+ try {
+ return ctor.newInstance(params);
+ } catch (InstantiationException xinstance) {
+ return TRY_FAILED;
+ } catch (IllegalAccessException xaccess) {
+ return TRY_FAILED;
+ } catch (IllegalArgumentException xargument) {
+ return TRY_FAILED;
+ } catch (InvocationTargetException xinvoke) {
+ return TRY_FAILED;
+ }
+ }
+ return TRY_FAILED;
+ }
+
+ public boolean tryFailed(Object rval) {
+ return rval == TRY_FAILED;
+ }
+
+ public boolean isCacheable() {
+ return true;
+ }
+
+ public Class<?> getReturnType() {
+ return ctor.getDeclaringClass();
+ }
+ };
+ return jctor;
+ }
+ return null;
}
/**
@@ -218,8 +279,8 @@ public class UberspectImpl extends Intro
*/
public Object tryInvoke(Object obj, Object key, Object value) {
if (obj.getClass().equals(field.getDeclaringClass())
- && key.equals(field.getName())
- && (value == null ||
MethodKey.isInvocationConvertible(field.getType(), value.getClass(), false))) {
+ && key.equals(field.getName())
+ && (value == null ||
MethodKey.isInvocationConvertible(field.getType(), value.getClass(), false))) {
try {
field.set(obj, value);
return value;
@@ -253,8 +314,8 @@ public class UberspectImpl extends Intro
if (set == null && obj != null && identifier != null) {
Field field = getField(obj, identifier.toString(), info);
if (field != null
- && !Modifier.isFinal(field.getModifiers())
- && (arg == null ||
MethodKey.isInvocationConvertible(field.getType(), arg.getClass(), false))) {
+ && !Modifier.isFinal(field.getModifiers())
+ && (arg == null ||
MethodKey.isInvocationConvertible(field.getType(), arg.getClass(), false))) {
return new FieldPropertySet(field);
}
}