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);
             }
         }


Reply via email to