Commits

Anonymous committed 0b24bb7

Added in as much support for varargs method calling as possible for OGNL-127, only to find out that javassist blows up on it. ..

  • Participants
  • Parent commits abc0bf1

Comments (0)

Files changed (6)

File src/java/ognl/ASTMethod.java

                 args[i] = _children[i].getValue(context, root);
             }
             
-            result = OgnlRuntime.callMethod(context, source, _methodName, null, args);
+            result = OgnlRuntime.callMethod(context, source, _methodName, args);
             
             if (result == null)
             {
                 _getterClass = m.getReturnType();
             }
 
+            boolean varArgs = OgnlRuntime.isJdk15() && m.isVarArgs();
+
             result = "." + m.getName() + "(";
             
-            if ((_children != null) && (_children.length > 0)) {
-                
+            if ((_children != null) && (_children.length > 0))
+            {    
                 Class[] parms = m.getParameterTypes();
                 String prevCast = (String)context.remove(ExpressionCompiler.PRE_CAST);
+                
 /*
                 System.out.println("before children methodName is " + _methodName + " for target " + target + " target class: " + (target != null ? target.getClass() : null)
                            + " current type: " + context.getCurrentType() + " and previous type: " + context.getPreviousType());*/
 
-                for(int i = 0; i < _children.length; i++) {
-                    if (i > 0) {
+                for(int i = 0; i < _children.length; i++)
+                {
+                    if (i > 0)
+                    {
                         result = result + ", ";
                     }
 
                         parmString = "null";
 
                     // to undo type setting of constants when used as method parameters
-                    if (ASTConst.class.isInstance(_children[i])) {
-                        
+                    if (ASTConst.class.isInstance(_children[i]))
+                    {    
                         context.setCurrentType(prevType);
                     }
 
                     parmString = ExpressionCompiler.getRootExpression(_children[i], context.getRoot(), context) + parmString;
 
                     String cast = "";
-                    if (ExpressionCompiler.shouldCast(_children[i])) {
-
+                    if (ExpressionCompiler.shouldCast(_children[i]))
+                    {
                         cast = (String)context.remove(ExpressionCompiler.PRE_CAST);
                     }
                     if (cast == null)
                     if (NodeType.class.isAssignableFrom(_children[i].getClass()))
                         valueClass = ((NodeType)_children[i]).getGetterClass();
 
-                    if (valueClass != parms[i]) {
-                        
+                    if ((!varArgs || varArgs && (i + 1) < parms.length) && valueClass != parms[i])
+                    {
                         if (parms[i].isArray()) {
 
                             parmString = OgnlRuntime.getCompiler().createLocalReference(context,
                     result += parmString;
                 }
 
-                if (prevCast != null) {
-                    
+                if (prevCast != null)
+                {    
                     context.put(ExpressionCompiler.PRE_CAST, prevCast);
                 }
             }

File src/java/ognl/MethodAccessor.java

 import java.util.Map;
 
 /**
- * This interface defines methods for callinig methods in a target object.
+ * This interface defines methods for calling methods in a target object.
  * Methods are broken up into static and instance methods for convenience.
  * indexes into the target object, which must be an array.
+ * 
  * @author Luke Blanshard (blanshlu@netscape.net)
  * @author Drew Davidson (drew@ognl.org)
  */

File src/java/ognl/OgnlRuntime.java

     {
         Object result;
         boolean wasAccessible = true;
+        Object[] arguments = argsArray;
 
         synchronized(method) {
 
                     ((AccessibleObject) method).setAccessible(true);
                 }
             }
-            result = method.invoke(target, argsArray);
+
+            if (isJdk15() && method.isVarArgs()) {
+                arguments = new Object[] { argsArray };
+            }
+
+            result = method.invoke(target, arguments);
             if (!wasAccessible) {
                 ((AccessibleObject) method).setAccessible(false);
             }
      * is, whether the given array of objects can be passed as arguments to a method or constructor
      * whose parameter types are the given array of classes.
      */
-    public static final boolean areArgsCompatible(Object[] args, Class[] classes)
+    public static boolean areArgsCompatible(Object[] args, Class[] classes)
+    {
+        return areArgsCompatible(args, classes, null);
+    }
+
+    public static boolean areArgsCompatible(Object[] args, Class[] classes, Method m)
     {
         boolean result = true;
+        boolean varArgs = m != null && isJdk15() && m.isVarArgs();
 
-        if (args.length != classes.length) {
+        if (args.length != classes.length && !varArgs) {
             result = false;
+        } else if (varArgs) {
+            for (int index = 0, count = args.length; result && (index < count); ++index) {
+                if (index >= classes.length){
+                    break;
+                }
+                result = isTypeCompatible(args[index], classes[index]) || classes[index].isArray();
+            }
         } else {
             for (int index = 0, count = args.length; result && (index < count); ++index) {
                 result = isTypeCompatible(args[index], classes[index]);
                 Method m = (Method) methods.get(i);
                 Class[] mParameterTypes = getParameterTypes(m);
 
-                if (areArgsCompatible(args, mParameterTypes)
+                if (areArgsCompatible(args, mParameterTypes, m)
                     && ((result == null) || isMoreSpecific(mParameterTypes, resultParameterTypes)))
                 {
                     result = m;
         }
     }
 
-    public static Object callMethod(OgnlContext context, Object target, String methodName,
-                                    String propertyName, Object[] args)
+    public static Object callMethod(OgnlContext context, Object target,
+                                    String methodName, Object[] args)
             throws OgnlException
     {
         if (target == null)
                 }
             }
 
-            return callMethod(context, source, m.getName(), name, args);
+            return callMethod(context, source, m.getName(), args);
 
         } catch (OgnlException ex) {
             throw ex;
                 }
             }
 
-            callMethod(context, source, m.getName(), name, args);
+            callMethod(context, source, m.getName(), args);
 
         } catch (OgnlException ex) {
             throw ex;
         _declaredMethods[1].setClassInspector(_cacheInspector);
     }
 
-    public static Method getMethod(OgnlContext context, Class target, String name, Node[] children, boolean includeStatic)
+    public static Method getMethod(OgnlContext context, Class target, String name,
+                                   Node[] children, boolean includeStatic)
             throws Exception
     {
         Class[] parms = null;
-        if (children != null && children.length > 0) {
-
+        if (children != null && children.length > 0)
+        {
             parms = new Class[children.length];
 
             // used to reset context after loop
             context.setCurrentAccessor(null);
             context.setPreviousType(null);
 
-            for (int i=0; i < children.length; i++) {
-
+            for (int i=0; i < children.length; i++)
+            {
                 children[i].toGetSourceString(context, context.getRoot());
                 parms[i] = context.getCurrentType();
             }
             context.setCurrentAccessor(currAccessor);
             context.setCurrentObject(target);
         } else
+        {
             parms = new Class[0];
+        }
 
         List methods = OgnlRuntime.getMethods(target, name, includeStatic);
         if (methods == null)
             return null;
 
-        for (int i = 0; i < methods.size(); i++) {
+        for (int i = 0; i < methods.size(); i++)
+        {
             Method m = (Method) methods.get(i);
-
-            if (parms.length != m.getParameterTypes().length)
+            boolean varArgs = isJdk15() && m.isVarArgs();
+            
+            if (parms.length != m.getParameterTypes().length && !varArgs)
                 continue;
 
             Class[] mparms = m.getParameterTypes();
             boolean matched = true;
-            for (int p = 0; p < mparms.length; p++) {
-
-                if (parms[p] == null) {
+            for (int p = 0; p < mparms.length; p++)
+            {
+                if (varArgs && mparms[p].isArray()){
+                    continue;
+                }
+                
+                if (parms[p] == null)
+                {
                     matched = false;
                     break;
                 }
                 if (mparms[p].isPrimitive()
                     && Character.TYPE != mparms[p] && Byte.TYPE != mparms[p]
                     && Number.class.isAssignableFrom(parms[p])
-                    && OgnlRuntime.getPrimitiveWrapperClass(parms[p]) == mparms[p]) {
+                    && OgnlRuntime.getPrimitiveWrapperClass(parms[p]) == mparms[p])
+                {
                     continue;
                 }
 

File src/test/java/ognl/TestOgnlRuntime.java

         ListSource list = new ListSourceImpl();
         OgnlContext context = (OgnlContext) Ognl.createDefaultContext(null);
 
-        Object ret = OgnlRuntime.callMethod(context, list, "addValue", null, new String[] {null});
+        Object ret = OgnlRuntime.callMethod(context, list, "addValue", new String[] {null});
         
         assert ret != null;
     }

File src/test/java/org/ognl/test/MethodTest.java

             { "isEditorDisabled()", Boolean.FALSE},
             { LIST, "addValue(name)", Boolean.TRUE},
             { "getDisplayValue(methodsTest.allowDisplay)", "test"},
+//            { "isThisVarArgsWorking(three, rootValue)", Boolean.TRUE}
     };
 
     public static class A

File src/test/java/org/ognl/test/objects/Simple.java

         }
         return result;
     }
+
+    public boolean isThisVarArgsWorking(Object...arguments)
+    {
+        return true;
+    }
 }