Clover coverage report - groovy - 1.0-beta-8
Coverage timestamp: Fri Dec 17 2004 14:55:55 GMT
file stats: LOC: 2,323   Methods: 80
NCLOC: 1,668   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
MetaClass.java 0% 0% 0% 0%
coverage
 1   
 /*
 2   
  $Id: MetaClass.java,v 1.85 2004/12/11 20:38:46 blackdrag Exp $
 3   
 
 4   
  Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
 5   
 
 6   
  Redistribution and use of this software and associated documentation
 7   
  ("Software"), with or without modification, are permitted provided
 8   
  that the following conditions are met:
 9   
 
 10   
  1. Redistributions of source code must retain copyright
 11   
     statements and notices.  Redistributions must also contain a
 12   
     copy of this document.
 13   
 
 14   
  2. Redistributions in binary form must reproduce the
 15   
     above copyright notice, this list of conditions and the
 16   
     following disclaimer in the documentation and/or other
 17   
     materials provided with the distribution.
 18   
 
 19   
  3. The name "groovy" must not be used to endorse or promote
 20   
     products derived from this Software without prior written
 21   
     permission of The Codehaus.  For written permission,
 22   
     please contact info@codehaus.org.
 23   
 
 24   
  4. Products derived from this Software may not be called "groovy"
 25   
     nor may "groovy" appear in their names without prior written
 26   
     permission of The Codehaus. "groovy" is a registered
 27   
     trademark of The Codehaus.
 28   
 
 29   
  5. Due credit should be given to The Codehaus -
 30   
     http://groovy.codehaus.org/
 31   
 
 32   
  THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
 33   
  ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
 34   
  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 35   
  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
 36   
  THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 37   
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 38   
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 39   
  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 40   
  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 41   
  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 42   
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 43   
  OF THE POSSIBILITY OF SUCH DAMAGE.
 44   
 
 45   
  */
 46   
 package groovy.lang;
 47   
 
 48   
 import java.beans.BeanInfo;
 49   
 import java.beans.EventSetDescriptor;
 50   
 import java.beans.IntrospectionException;
 51   
 import java.beans.Introspector;
 52   
 import java.beans.PropertyDescriptor;
 53   
 import java.lang.reflect.Array;
 54   
 import java.lang.reflect.Constructor;
 55   
 import java.lang.reflect.Field;
 56   
 import java.lang.reflect.InvocationHandler;
 57   
 import java.lang.reflect.InvocationTargetException;
 58   
 import java.lang.reflect.Method;
 59   
 import java.lang.reflect.Modifier;
 60   
 import java.lang.reflect.Proxy;
 61   
 import java.math.BigDecimal;
 62   
 import java.math.BigInteger;
 63   
 import java.net.URL;
 64   
 import java.security.AccessControlException;
 65   
 import java.security.AccessController;
 66   
 import java.security.PrivilegedAction;
 67   
 import java.security.PrivilegedActionException;
 68   
 import java.security.PrivilegedExceptionAction;
 69   
 import java.util.ArrayList;
 70   
 import java.util.Arrays;
 71   
 import java.util.Collection;
 72   
 import java.util.Collections;
 73   
 import java.util.HashMap;
 74   
 import java.util.Iterator;
 75   
 import java.util.List;
 76   
 import java.util.Map;
 77   
 import java.util.logging.Logger;
 78   
 
 79   
 import org.codehaus.groovy.ast.ClassNode;
 80   
 import org.codehaus.groovy.classgen.ReflectorGenerator;
 81   
 import org.codehaus.groovy.control.CompilationUnit;
 82   
 import org.codehaus.groovy.control.Phases;
 83   
 import org.codehaus.groovy.runtime.ClosureListener;
 84   
 import org.codehaus.groovy.runtime.DefaultGroovyMethods;
 85   
 import org.codehaus.groovy.runtime.GroovyCategorySupport;
 86   
 import org.codehaus.groovy.runtime.InvokerHelper;
 87   
 import org.codehaus.groovy.runtime.InvokerInvocationException;
 88   
 import org.codehaus.groovy.runtime.MethodClosure;
 89   
 import org.codehaus.groovy.runtime.MethodHelper;
 90   
 import org.codehaus.groovy.runtime.MethodKey;
 91   
 import org.codehaus.groovy.runtime.NewInstanceMetaMethod;
 92   
 import org.codehaus.groovy.runtime.NewStaticMetaMethod;
 93   
 import org.codehaus.groovy.runtime.ReflectionMetaMethod;
 94   
 import org.codehaus.groovy.runtime.Reflector;
 95   
 import org.codehaus.groovy.runtime.TemporaryMethodKey;
 96   
 import org.codehaus.groovy.runtime.TransformMetaMethod;
 97   
 import org.objectweb.asm.ClassVisitor;
 98   
 import org.objectweb.asm.ClassWriter;
 99   
 
 100   
 /**
 101   
  * Allows methods to be dynamically added to existing classes at runtime
 102   
  * 
 103   
  * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
 104   
  * @author Guillaume Laforge
 105   
  * @version $Revision: 1.85 $
 106   
  */
 107   
 public class MetaClass {
 108   
 
 109   
     private static final Logger log = Logger.getLogger(MetaClass.class.getName());
 110   
 
 111   
     public static final Object[] EMPTY_ARRAY = {
 112   
     };
 113   
     public static Class[] EMPTY_TYPE_ARRAY = {
 114   
     };
 115   
     protected static final Object[] ARRAY_WITH_NULL = { null };
 116   
 
 117   
     private static boolean useReflection = false;
 118   
 
 119   
     private MetaClassRegistry registry;
 120   
     private Class theClass;
 121   
     private ClassNode classNode;
 122   
     private Map methodIndex = new HashMap();
 123   
     private Map staticMethodIndex = new HashMap();
 124   
     private List newGroovyMethodsList = new ArrayList();
 125   
     //private Map propertyDescriptors = Collections.synchronizedMap(new HashMap());
 126   
     private Map propertyMap = Collections.synchronizedMap(new HashMap());
 127   
     private Map listeners = new HashMap();
 128   
     private Map methodCache = Collections.synchronizedMap(new HashMap());
 129   
     private Map staticMethodCache = Collections.synchronizedMap(new HashMap());
 130   
     private MetaMethod genericGetMethod;
 131   
     private MetaMethod genericSetMethod;
 132   
     private List constructors;
 133   
     private List allMethods = new ArrayList();
 134   
     private List interfaceMethods;
 135   
     private Reflector reflector;
 136   
     private boolean initialised;
 137   
     // we only need one of these that can be reused over and over.
 138   
     private MetaProperty arrayLengthProperty = new MetaArrayLengthProperty();
 139   
     
 140  0
     public MetaClass(MetaClassRegistry registry, final Class theClass) throws IntrospectionException {
 141  0
         this.registry = registry;
 142  0
         this.theClass = theClass;
 143   
 
 144  0
         constructors = Arrays.asList(theClass.getDeclaredConstructors());
 145  0
         addMethods(theClass);
 146   
 
 147   
         // introspect
 148  0
         BeanInfo info = null;
 149  0
         try {
 150  0
             info =(BeanInfo) AccessController.doPrivileged(new PrivilegedExceptionAction() {
 151  0
                 public Object run() throws IntrospectionException {
 152  0
                     return Introspector.getBeanInfo(theClass);
 153   
                 }
 154   
             });
 155   
         } catch (PrivilegedActionException pae) {
 156  0
             if (pae.getException() instanceof IntrospectionException) {
 157  0
                 throw (IntrospectionException) pae.getException();
 158   
             } else {
 159  0
                 throw new RuntimeException(pae.getException());
 160   
             }
 161   
         }
 162   
 
 163  0
         PropertyDescriptor[] descriptors = info.getPropertyDescriptors();
 164   
         
 165   
         // build up the metaproperties based on the public fields, property descriptors,
 166   
         // and the getters and setters
 167  0
         setupProperties(descriptors);
 168   
         
 169   
         /* old code
 170   
         for (int i = 0; i < descriptors.length; i++) {
 171   
             PropertyDescriptor descriptor = descriptors[i];
 172   
             propertyDescriptors.put(descriptor.getName(), descriptor);
 173   
         }
 174   
         */
 175   
         
 176  0
         EventSetDescriptor[] eventDescriptors = info.getEventSetDescriptors();
 177  0
         for (int i = 0; i < eventDescriptors.length; i++) {
 178  0
             EventSetDescriptor descriptor = eventDescriptors[i];
 179  0
             Method[] listenerMethods = descriptor.getListenerMethods();
 180  0
             for (int j = 0; j < listenerMethods.length; j++) {
 181  0
                 Method listenerMethod = listenerMethods[j];
 182  0
                 MetaMethod metaMethod = createMetaMethod(descriptor.getAddListenerMethod());
 183  0
                 listeners.put(listenerMethod.getName(), metaMethod);
 184   
             }
 185   
         }
 186   
     }
 187   
 
 188  0
     public static boolean isUseReflection() {
 189  0
         return useReflection;
 190   
     }
 191   
 
 192   
     /**
 193   
      * Allows reflection to be enabled in situations where bytecode generation
 194   
      * of method invocations causes issues.
 195   
      * 
 196   
      * @param useReflection
 197   
      */
 198  0
     public static void setUseReflection(boolean useReflection) {
 199  0
         MetaClass.useReflection = useReflection;
 200   
     }
 201   
 
 202  0
     private void addInheritedMethods(Class theClass) {
 203   
         // lets add all the base class methods
 204  0
         Class c = theClass;
 205  0
         if (c != Object.class) {
 206  0
             while (true) {
 207  0
                 c = c.getSuperclass();
 208  0
                 if (c == Object.class || c == null) {
 209  0
                     break;
 210   
                 }
 211  0
                 addMethods(c);
 212  0
                 addNewStaticMethodsFrom(c);
 213   
 
 214   
             }
 215   
         }
 216   
 
 217   
         // now lets see if there are any methods on one of my interfaces
 218  0
         Class[] interfaces = theClass.getInterfaces();
 219  0
         for (int i = 0; i < interfaces.length; i++) {
 220  0
             addNewStaticMethodsFrom(interfaces[i]);
 221   
         }
 222   
 
 223   
         // lets add Object methods after interfaces, as all interfaces derive from Object. 
 224   
         // this ensures List and Collection methods come before Object etc
 225  0
         if (theClass != Object.class) {
 226  0
             addMethods(Object.class);
 227  0
             addNewStaticMethodsFrom(Object.class);
 228   
         }
 229   
 
 230  0
         if (theClass.isArray() && !theClass.equals(Object[].class)) {
 231  0
             addNewStaticMethodsFrom(Object[].class);
 232   
         }
 233   
     }
 234   
 
 235   
     /**
 236   
      * @return all the normal instance methods avaiable on this class for the
 237   
      *         given name
 238   
      */
 239  0
     public List getMethods(String name) {
 240  0
         List answer = (List) methodIndex.get(name);
 241  0
         List used = GroovyCategorySupport.getCategoryMethods(theClass, name);
 242  0
         if (used != null) {
 243  0
             if (answer != null) {
 244  0
                 answer.addAll(used);
 245   
             } else{
 246  0
                 answer = used;
 247   
             }
 248   
         }
 249  0
         if (answer == null) {
 250  0
             answer = Collections.EMPTY_LIST;
 251   
         }
 252  0
         return answer;
 253   
     }
 254   
 
 255   
     /**
 256   
      * @return all the normal static methods avaiable on this class for the
 257   
      *         given name
 258   
      */
 259  0
     public List getStaticMethods(String name) {
 260  0
         List answer = (List) staticMethodIndex.get(name);
 261  0
         if (answer == null) {
 262  0
             return Collections.EMPTY_LIST;
 263   
         }
 264  0
         return answer;
 265   
     }
 266   
 
 267   
     /**
 268   
      * Allows static method definitions to be added to a meta class as if it
 269   
      * was an instance method
 270   
      * 
 271   
      * @param method
 272   
      */
 273  0
     protected void addNewInstanceMethod(Method method) {
 274  0
         if (initialised) {
 275  0
             throw new RuntimeException("Already initialized, cannot add new method: " + method);
 276   
         }
 277   
         else {
 278  0
             NewInstanceMetaMethod newMethod = new NewInstanceMetaMethod(createMetaMethod(method));
 279  0
             addMethod(newMethod);
 280  0
             addNewInstanceMethod(newMethod);
 281   
         }
 282   
     }
 283   
 
 284  0
     protected void addNewInstanceMethod(MetaMethod method) {
 285  0
         newGroovyMethodsList.add(method);
 286   
     }
 287   
 
 288  0
     protected void addNewStaticMethod(Method method) {
 289  0
         if (initialised) {
 290  0
             throw new RuntimeException("Already initialized, cannot add new method: " + method);
 291   
         }
 292   
         else {
 293  0
             NewStaticMetaMethod newMethod = new NewStaticMetaMethod(createMetaMethod(method));
 294  0
             addMethod(newMethod);
 295  0
             addNewStaticMethod(newMethod);
 296   
         }
 297   
     }
 298   
 
 299  0
     protected void addNewStaticMethod(MetaMethod method) {
 300  0
         newGroovyMethodsList.add(method);
 301   
     }
 302   
 
 303  0
     public Object invokeMethod(Object object, String methodName, Object arguments) {
 304  0
         return invokeMethod(object, methodName, asArray(arguments));
 305   
     }
 306   
 
 307   
     /**
 308   
      * Invokes the given method on the object.
 309   
      *  
 310   
      */
 311  0
     public Object invokeMethod(Object object, String methodName, Object[] arguments) {
 312  0
         if (object == null) {
 313  0
             throw new NullPointerException("Cannot invoke method: " + methodName + " on null object");
 314   
         }
 315   
 
 316  0
         MetaMethod method = retrieveMethod(object, methodName, arguments);
 317   
 
 318  0
         if (method != null) {
 319  0
             return doMethodInvoke(object, method, arguments);
 320   
         } else {
 321   
             // if no method was found, try to find a closure defined as a field of the class and run it
 322  0
             try {
 323  0
                 Object value = this.getProperty(object, methodName);
 324  0
                 if (value instanceof Closure) {
 325  0
                     Closure closure = (Closure) value;
 326  0
                     closure.setDelegate(this);
 327  0
                     return closure.call(arguments);
 328   
                 }
 329   
                 else {
 330  0
                     throw new MissingMethodException(methodName, theClass, arguments);
 331   
                 }
 332   
             }
 333   
             catch (Exception e) {
 334  0
                 throw new MissingMethodException(methodName, theClass, arguments);
 335   
             }
 336   
         }
 337   
     }
 338   
 
 339  0
     protected MetaMethod retrieveMethod(Object owner, String methodName, Object[] arguments) {
 340   
         // lets try use the cache to find the method
 341  0
         MethodKey methodKey = new TemporaryMethodKey(methodName, arguments);
 342  0
         MetaMethod method = (MetaMethod) methodCache.get(methodKey);
 343  0
         if (method == null) {
 344  0
             method = pickMethod(owner, methodName, arguments);
 345  0
             if (method != null && method.isCacheable()) {
 346  0
                 methodCache.put(methodKey.createCopy(), method);
 347   
             }
 348   
         }
 349  0
         return method;
 350   
     }
 351   
 
 352  0
     public MetaMethod retrieveMethod(String methodName, Class[] arguments) {
 353   
         // lets try use the cache to find the method
 354  0
         MethodKey methodKey = new TemporaryMethodKey(methodName, arguments);
 355  0
         MetaMethod method = (MetaMethod) methodCache.get(methodKey);
 356  0
         if (method == null) {
 357  0
             method = pickMethod(methodName, arguments); // todo shall call pickStaticMethod also?
 358  0
             if (method != null && method.isCacheable()) {
 359  0
                 methodCache.put(methodKey.createCopy(), method);
 360   
             }
 361   
         }
 362  0
         return method;
 363   
     }
 364   
 
 365  0
     public Constructor retrieveConstructor(Class[] arguments) {
 366  0
         Constructor constructor = (Constructor) chooseMethod("<init>", constructors, arguments, false);
 367  0
         if (constructor != null) {
 368  0
             return constructor;
 369   
         }
 370   
         else {
 371  0
             constructor = (Constructor) chooseMethod("<init>", constructors, arguments, true);
 372  0
             if (constructor != null) {
 373  0
                 return constructor;
 374   
             }
 375   
         }
 376  0
         return null;
 377   
     }
 378   
 
 379  0
     public MetaMethod retrieveStaticMethod(String methodName, Class[] arguments) {
 380  0
         MethodKey methodKey = new TemporaryMethodKey(methodName, arguments);
 381  0
         MetaMethod method = (MetaMethod) staticMethodCache.get(methodKey);
 382  0
         if (method == null) {
 383  0
             method = pickStaticMethod(methodName, arguments);
 384  0
             if (method != null) {
 385  0
                 staticMethodCache.put(methodKey.createCopy(), method);
 386   
             }
 387   
         }
 388  0
         return method;
 389   
     }
 390   
     /**
 391   
      * Picks which method to invoke for the given object, method name and arguments
 392   
      */
 393  0
     protected MetaMethod pickMethod(Object object, String methodName, Object[] arguments) {
 394  0
         MetaMethod method = null;
 395  0
         List methods = getMethods(methodName);
 396  0
         if (!methods.isEmpty()) {
 397  0
             Class[] argClasses = convertToTypeArray(arguments);
 398  0
             method = (MetaMethod) chooseMethod(methodName, methods, argClasses, false);
 399  0
             if (method == null) {
 400  0
                 method = (MetaMethod) chooseMethod(methodName, methods, argClasses, true);
 401  0
                 if (method == null) {
 402  0
                     int size = (arguments != null) ? arguments.length : 0;
 403  0
                     if (size == 1) {
 404  0
                         Object firstArgument = arguments[0];
 405  0
                         if (firstArgument instanceof List) {
 406   
                             // lets coerce the list arguments into an array of
 407   
                             // arguments
 408   
                             // e.g. calling JFrame.setLocation( [100, 100] )
 409   
 
 410  0
                             List list = (List) firstArgument;
 411  0
                             arguments = list.toArray();
 412  0
                             argClasses = convertToTypeArray(arguments);
 413  0
                             method = (MetaMethod) chooseMethod(methodName, methods, argClasses, true);
 414  0
                             if (method==null) return null;
 415  0
                             return new TransformMetaMethod(method) {
 416  0
                                 public Object invoke(Object object, Object[] arguments) throws Exception {
 417  0
                                     Object firstArgument = arguments[0];
 418  0
                                     List list = (List) firstArgument;
 419  0
                                     arguments = list.toArray();
 420  0
                                     return super.invoke(object, arguments);
 421   
                                 }
 422   
                             };
 423   
                         }
 424   
                     }
 425   
                 }
 426   
             }
 427   
         }
 428  0
         return method;
 429   
     }
 430   
 
 431   
     /**
 432   
      * pick a method in a strict manner, i.e., without reinterpreting the first List argument.
 433   
      * this method is used only by ClassGenerator for static binding
 434   
      * @param methodName
 435   
      * @param arguments
 436   
      * @return
 437   
      */
 438  0
     protected MetaMethod pickMethod(String methodName, Class[] arguments) {
 439  0
         MetaMethod method = null;
 440  0
         List methods = getMethods(methodName);
 441  0
         if (!methods.isEmpty()) {
 442  0
             method = (MetaMethod) chooseMethod(methodName, methods, arguments, false);
 443   
 // no coersion at classgen time.
 444   
 //            if (method == null) {
 445   
 //                method = (MetaMethod) chooseMethod(methodName, methods, arguments, true);
 446   
 //            }
 447   
         }
 448  0
         return method;
 449   
     }
 450   
 
 451  0
     public Object invokeStaticMethod(Object object, String methodName, Object[] arguments) {
 452   
         //        System.out.println("Calling static method: " + methodName + " on args: " + InvokerHelper.toString(arguments));
 453   
         //        Class type = arguments == null ? null : arguments.getClass();
 454   
         //        System.out.println("Argument  type: " + type);
 455   
         //        System.out.println("Type of first arg: " + arguments[0] + " type: " + arguments[0].getClass());
 456   
 
 457   
         // lets try use the cache to find the method
 458  0
         MethodKey methodKey = new TemporaryMethodKey(methodName, arguments);
 459  0
         MetaMethod method = (MetaMethod) staticMethodCache.get(methodKey);
 460  0
         if (method == null) {
 461  0
             method = pickStaticMethod(object, methodName, arguments);
 462  0
             if (method != null) {
 463  0
                 staticMethodCache.put(methodKey.createCopy(), method);
 464   
             }
 465   
         }
 466   
 
 467  0
         if (method != null) {
 468  0
             return doMethodInvoke(object, method, arguments);
 469   
         }
 470   
         /*
 471   
         List methods = getStaticMethods(methodName);
 472   
         
 473   
         if (!methods.isEmpty()) {
 474   
             MetaMethod method = (MetaMethod) chooseMethod(methodName, methods, arguments, false);
 475   
             if (method != null) {
 476   
                 return doMethodInvoke(theClass, method, arguments);
 477   
             }
 478   
         }
 479   
         
 480   
         if (theClass != Class.class) {
 481   
             try {
 482   
                 return registry.getMetaClass(Class.class).invokeMethod(object, methodName, arguments);
 483   
             }
 484   
             catch (GroovyRuntimeException e) {
 485   
                 // throw our own exception
 486   
             }
 487   
         }
 488   
         */
 489  0
         throw new MissingMethodException(methodName, theClass, arguments);
 490   
     }
 491   
 
 492  0
     protected MetaMethod pickStaticMethod(Object object, String methodName, Object[] arguments) {
 493  0
         MetaMethod method = null;
 494  0
         List methods = getStaticMethods(methodName);
 495   
 
 496  0
         if (!methods.isEmpty()) {
 497  0
             method = (MetaMethod) chooseMethod(methodName, methods, convertToTypeArray(arguments), false);
 498   
         }
 499   
 
 500  0
         if (method == null && theClass != Class.class) {
 501  0
             MetaClass classMetaClass = registry.getMetaClass(Class.class);
 502  0
             method = classMetaClass.pickMethod(object, methodName, arguments);
 503   
         }
 504  0
         return method;
 505   
     }
 506   
 
 507  0
     protected MetaMethod pickStaticMethod(String methodName, Class[] arguments) {
 508  0
         MetaMethod method = null;
 509  0
         List methods = getStaticMethods(methodName);
 510   
 
 511  0
         if (!methods.isEmpty()) {
 512  0
             method = (MetaMethod) chooseMethod(methodName, methods, arguments, false);
 513   
 // disabled to keep consistant with the original version of pickStatciMethod
 514   
 //            if (method == null) {
 515   
 //                method = (MetaMethod) chooseMethod(methodName, methods, arguments, true);
 516   
 //            }
 517   
         }
 518   
 
 519  0
         if (method == null && theClass != Class.class) {
 520  0
             MetaClass classMetaClass = registry.getMetaClass(Class.class);
 521  0
             method = classMetaClass.pickMethod(methodName, arguments);
 522   
         }
 523  0
         return method;
 524   
     }
 525   
 
 526  0
     public Object invokeConstructor(Object[] arguments) {
 527  0
         Class[] argClasses = convertToTypeArray(arguments);
 528  0
         Constructor constructor = (Constructor) chooseMethod("<init>", constructors, argClasses, false);
 529  0
         if (constructor != null) {
 530  0
             return doConstructorInvoke(constructor, arguments);
 531   
         }
 532   
         else {
 533  0
             constructor = (Constructor) chooseMethod("<init>", constructors, argClasses, true);
 534  0
             if (constructor != null) {
 535  0
                 return doConstructorInvoke(constructor, arguments);
 536   
             }
 537   
         }
 538   
 
 539  0
         if (arguments.length == 1) {
 540  0
             Object firstArgument = arguments[0];
 541  0
             if (firstArgument instanceof Map) {
 542  0
                 constructor = (Constructor) chooseMethod("<init>", constructors, EMPTY_TYPE_ARRAY, false);
 543  0
                 if (constructor != null) {
 544  0
                     Object bean = doConstructorInvoke(constructor, EMPTY_ARRAY);
 545  0
                     setProperties(bean, ((Map) firstArgument));
 546  0
                     return bean;
 547   
                 }
 548   
             }
 549   
         }
 550  0
         throw new GroovyRuntimeException(
 551   
                     "Could not find matching constructor for: "
 552   
                         + theClass.getName()
 553   
                         + "("+InvokerHelper.toTypeString(arguments)+")");
 554   
     }
 555   
 
 556   
     /**
 557   
      * Sets a number of bean properties from the given Map where the keys are
 558   
      * the String names of properties and the values are the values of the
 559   
      * properties to set
 560   
      */
 561  0
     public void setProperties(Object bean, Map map) {
 562  0
         for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) {
 563  0
             Map.Entry entry = (Map.Entry) iter.next();
 564  0
             String key = entry.getKey().toString();
 565   
             
 566   
             // do we have this property?
 567  0
             if(propertyMap.get(key) == null)
 568  0
                 continue;
 569   
             
 570  0
             Object value = entry.getValue();
 571  0
             try {
 572  0
                 setProperty(bean, key, value);
 573   
             }
 574   
             catch (GroovyRuntimeException e) {
 575   
                 // lets ignore missing properties
 576   
                 /** todo should replace this code with a getMetaProperty(key) != null check
 577   
                  i.e. don't try and set a non-existent property
 578   
                  */
 579   
             }
 580   
         }
 581   
     }
 582   
 
 583   
     /**
 584   
      * @return the given property's value on the object
 585   
      */
 586  0
     public Object getProperty(final Object object, final String property) {
 587   
         /* old code; we now use the metaProperty map to handle properties
 588   
         MetaMethod metaMethod = null;
 589   
         PropertyDescriptor descriptor = (PropertyDescriptor) propertyDescriptors.get(property);
 590   
         if (descriptor != null) {
 591   
             Method method = descriptor.getReadMethod();
 592   
             if (method == null) {
 593   
                 throw new GroovyRuntimeException("Cannot read property: " + property);
 594   
             }
 595   
             metaMethod = findMethod(method);
 596   
             if (metaMethod == null) {
 597   
                 // lets try invoke a static getter method
 598   
                 metaMethod = findGetter(object, "get" + capitalize(property));
 599   
             }
 600   
             if (metaMethod != null) {
 601   
                 return doMethodInvoke(object, metaMethod, EMPTY_ARRAY);
 602   
             }
 603   
         }
 604   
         */
 605   
         
 606   
         // look for the property in our map
 607  0
         MetaProperty mp = (MetaProperty) propertyMap.get(property);
 608  0
         if(mp != null) {
 609  0
             try {
 610   
                 //System.out.println("we found a metaproperty for " + theClass.getName() +
 611   
                 //  "." + property);
 612   
                 // delegate the get operation to the metaproperty
 613  0
                 return mp.getProperty(object);
 614   
             }
 615   
             catch(Exception e) {
 616  0
                 throw new GroovyRuntimeException("Cannot read property: " + property);
 617   
             }
 618   
         }
 619   
 
 620  0
         if (genericGetMethod == null) {
 621   
             // Make sure there isn't a generic method in the "use" cases
 622  0
             List possibleGenericMethods = getMethods("get");
 623  0
             if (possibleGenericMethods != null) {
 624  0
                 for (Iterator i = possibleGenericMethods.iterator(); i.hasNext(); ) {
 625  0
                     MetaMethod mmethod = (MetaMethod) i.next();
 626  0
                     Class[] paramTypes = mmethod.getParameterTypes();
 627  0
                     if (paramTypes.length == 1 && paramTypes[0] == String.class) {
 628  0
                         Object[] arguments = {property};
 629  0
                         Object answer = doMethodInvoke(object, mmethod, arguments);
 630  0
                         return answer;
 631   
                     }
 632   
                 }
 633   
             }
 634   
         } 
 635   
         else {
 636  0
             Object[] arguments = { property };
 637  0
             Object answer = doMethodInvoke(object, genericGetMethod, arguments);
 638   
             // jes bug? a property retrieved via a generic get() can't have a null value?
 639  0
             if (answer != null) {
 640  0
                 return answer;
 641   
             }
 642   
         }
 643   
 
 644   
         // is the property the name of a method - in which case return a
 645   
         // closure
 646  0
         List methods = getMethods(property);
 647  0
         if (!methods.isEmpty()) {
 648  0
             return new MethodClosure(object, property);
 649   
         }
 650   
 
 651   
         // lets try invoke a static getter method
 652   
         // this case is for protected fields. I wish there was a better way...
 653  0
         Exception lastException = null;
 654  0
         try {
 655  0
             MetaMethod method = findGetter(object, "get" + capitalize(property));
 656  0
             if (method != null) {
 657  0
                 return doMethodInvoke(object, method, EMPTY_ARRAY);
 658   
             }
 659   
         }
 660   
         catch (GroovyRuntimeException e) {
 661  0
             lastException = e;
 662   
         }
 663   
 
 664   
         /** todo or are we an extensible groovy class? */
 665  0
         if (genericGetMethod != null) {
 666  0
             return null;
 667   
         }
 668   
         else {
 669   
             /** todo these special cases should be special MetaClasses maybe */
 670  0
             if (object instanceof Class) {
 671   
                 // lets try a static field
 672  0
                 return getStaticProperty((Class) object, property);
 673   
             }
 674  0
             if (object instanceof Collection) {
 675  0
                 return DefaultGroovyMethods.getAt((Collection) object, property);
 676   
             }
 677  0
             if (object instanceof Object[]) {
 678  0
                 return DefaultGroovyMethods.getAt(Arrays.asList((Object[]) object), property);
 679   
             }
 680  0
             if (object instanceof Object) {
 681  0
                 try {
 682   
                     // lets try a public field
 683  0
                     Field field = object.getClass().getDeclaredField(property);
 684  0
                     return field.get(object);
 685   
                 }
 686   
                 catch (Exception e1) {
 687   
                     // fall through
 688   
                 }
 689   
             }
 690   
             
 691  0
             MetaMethod addListenerMethod = (MetaMethod) listeners.get(property);
 692  0
             if (addListenerMethod != null) {
 693   
                 /* @todo one day we could try return the previously registered Closure listener for easy removal */
 694  0
                 return null;
 695   
             }
 696   
 
 697  0
             if (lastException == null)
 698  0
                 throw new MissingPropertyException(property, theClass);
 699   
             else
 700  0
                 throw new MissingPropertyException(property, theClass, lastException);
 701   
         }
 702   
     }
 703   
     
 704   
     /**
 705   
      * Get all the properties defined for this type
 706   
      * @return a list of MetaProperty objects
 707   
      */
 708  0
     public List getProperties() {
 709   
         // simply return the values of the metaproperty map as a List
 710  0
         return new ArrayList(propertyMap.values());
 711   
     }
 712   
     
 713   
     /**
 714   
      * This will build up the property map (Map of MetaProperty objects, keyed on 
 715   
      * property name).
 716   
      */
 717  0
     protected void setupProperties(PropertyDescriptor[] propertyDescriptors) {
 718  0
         MetaProperty mp;
 719  0
         Method method;
 720  0
         MetaMethod getter = null;
 721  0
         MetaMethod setter = null;
 722  0
         Class klass;
 723   
         
 724   
         // first get the public fields and create MetaFieldProperty objects
 725  0
         klass = theClass;
 726  0
         while(klass != null) {
 727  0
             Field[] fields = klass.getDeclaredFields();
 728  0
             for(int i = 0; i < fields.length; i++) {
 729   
                 // we're only interested in publics
 730  0
                 if((fields[i].getModifiers() & java.lang.reflect.Modifier.PUBLIC) == 0)
 731  0
                     continue;
 732   
                 
 733   
                 // see if we already got this
 734  0
                 if(propertyMap.get(fields[i].getName()) != null)
 735  0
                     continue;
 736   
                 
 737   
                 //System.out.println("adding field " + fields[i].getName() + 
 738   
                 //  " for class " + klass.getName());
 739   
                 // stick it in there!
 740  0
                 propertyMap.put(fields[i].getName(), new MetaFieldProperty(fields[i]));
 741   
             }
 742   
             
 743   
             // now get the super class
 744  0
             klass = klass.getSuperclass();
 745   
         }
 746   
         
 747   
         // if this an Array, then add the special read-only "length" property
 748  0
         if(theClass.isArray()) {
 749  0
             propertyMap.put("length", arrayLengthProperty);
 750   
         }
 751   
         
 752   
         // now iterate over the map of property descriptors and generate 
 753   
         // MetaBeanProperty objects
 754  0
         for(int i=0; i<propertyDescriptors.length; i++) {
 755  0
             PropertyDescriptor pd = propertyDescriptors[i];
 756   
             // skip if the field already exists in the map
 757  0
             if(propertyMap.get(pd.getName()) != null)
 758  0
                 continue;
 759   
             
 760   
             // skip if the property type is unknown (this seems to be the case if the 
 761   
             // property descriptor is based on a setX() method that has two parameters,
 762   
             // which is not a valid property)
 763  0
             if(pd.getPropertyType() == null)
 764  0
                 continue;
 765   
             
 766   
             // get the getter method
 767  0
             method = pd.getReadMethod();
 768  0
             if(method != null)
 769  0
                 getter = findMethod(method);
 770   
             else
 771  0
                 getter = null;
 772   
             
 773   
             // get the setter method
 774  0
             method = pd.getWriteMethod();
 775  0
             if(method != null)
 776  0
                 setter = findMethod(method);
 777   
             else
 778  0
                 setter = null;
 779   
             
 780   
             // now create the MetaProperty object
 781   
             //System.out.println("creating a bean property for class " +
 782   
             //  theClass.getName() + ": " + pd.getName());
 783   
                 
 784  0
             mp = new MetaBeanProperty(pd.getName(), pd.getPropertyType(), getter, setter);
 785   
             
 786   
             // put it in the list
 787  0
             propertyMap.put(pd.getName(), mp);
 788   
         }
 789   
         
 790   
         // now look for any stray getters that may be used to define a property
 791  0
         klass = theClass;
 792  0
         while(klass != null) {
 793  0
             Method[] methods = klass.getDeclaredMethods();
 794  0
             for (int i = 0; i < methods.length; i++) {
 795   
                 // filter out the privates
 796  0
                 if(Modifier.isPublic(methods[i].getModifiers()) == false)
 797  0
                     continue;
 798   
                 
 799  0
                 method = methods[i];
 800   
                 
 801  0
                 String methodName = method.getName();
 802   
                 
 803   
                 // is this a getter?
 804  0
                 if(methodName.startsWith("get") && 
 805   
                     methodName.length() > 3 &&
 806   
                     method.getParameterTypes().length == 0) {
 807   
                     
 808   
                     // get the name of the property
 809  0
                     String propName = methodName.substring(3,4).toLowerCase() + methodName.substring(4);
 810   
                     
 811   
                     // is this property already accounted for?
 812  0
                     mp = (MetaProperty) propertyMap.get(propName);
 813  0
                     if(mp != null) {
 814   
                         // we may have already found the setter for this
 815  0
                         if(mp instanceof MetaBeanProperty && ((MetaBeanProperty) mp).getGetter() == null) {
 816   
                             // update the getter method to this one
 817  0
                             ((MetaBeanProperty) mp).setGetter(findMethod(method));
 818   
                         }
 819   
                     }
 820   
                     else {
 821   
                         // we need to create a new property object
 822   
                         // type of the property is what the get method returns
 823  0
                         MetaBeanProperty mbp = new MetaBeanProperty(propName, 
 824   
                             method.getReturnType(),
 825   
                             findMethod(method), null);
 826   
                             
 827   
                         // add it to the map
 828  0
                         propertyMap.put(propName, mbp);
 829   
                     }
 830   
                 }
 831  0
                 else if(methodName.startsWith("set") && 
 832   
                     methodName.length() > 3 &&
 833   
                     method.getParameterTypes().length == 1) {
 834   
                     
 835   
                     // get the name of the property
 836  0
                     String propName = methodName.substring(3,4).toLowerCase() + methodName.substring(4);
 837   
                     
 838   
                     // did we already find the getter of this?
 839  0
                     mp = (MetaProperty) propertyMap.get(propName);
 840  0
                     if(mp != null) {
 841  0
                         if(mp instanceof MetaBeanProperty && ((MetaBeanProperty) mp).getSetter() == null) {
 842   
                             // update the setter method to this one
 843  0
                             ((MetaBeanProperty) mp).setSetter(findMethod(method));
 844   
                         }
 845   
                     }
 846   
                     else {
 847   
                         // this is a new property to add
 848  0
                         MetaBeanProperty mbp = new MetaBeanProperty(propName, 
 849   
                                                                     method.getParameterTypes()[0],
 850   
                                                                     null,
 851   
                                                                     findMethod(method));
 852   
                             
 853   
                         // add it to the map
 854  0
                         propertyMap.put(propName, mbp);
 855   
                     }
 856   
                 }
 857   
             }
 858   
             
 859   
             // now get the super class
 860  0
             klass = klass.getSuperclass();
 861   
         }
 862   
     }
 863   
     
 864   
     /**
 865   
      * Sets the property value on an object
 866   
      */
 867  0
     public void setProperty(Object object, String property, Object newValue) {
 868   
         /* old code, replaced with new MetaProperty stuff...
 869   
         PropertyDescriptor descriptor = (PropertyDescriptor) propertyDescriptors.get(property);
 870   
 
 871   
         if (descriptor != null) {
 872   
             Method method = descriptor.getWriteMethod();
 873   
             if (method == null) {
 874   
                 throw new ReadOnlyPropertyException(property, theClass);
 875   
             }
 876   
             MetaMethod metaMethod = findMethod(method);
 877   
             Object[] arguments = { newValue };
 878   
             try {
 879   
                 doMethodInvoke(object, metaMethod, arguments);
 880   
             }
 881   
             catch (GroovyRuntimeException e) {
 882   
                 // if the value is a List see if we can construct the value
 883   
                 // from a constructor
 884   
                 if (newValue instanceof List) {
 885   
                     List list = (List) newValue;
 886   
                     int params = list.size();
 887   
                     Constructor[] propConstructors = descriptor.getPropertyType().getConstructors();
 888   
                     for (int i = 0; i < propConstructors.length; i++) {
 889   
                         Constructor constructor = propConstructors[i];
 890   
                         if (constructor.getParameterTypes().length == params) {
 891   
                             Object value = doConstructorInvoke(constructor, list.toArray());
 892   
                             doMethodInvoke(object, metaMethod, new Object[] { value });
 893   
                             return;
 894   
                         }
 895   
                     }
 896   
                     
 897   
                     // if value is an array  
 898   
                     Class parameterType = method.getParameterTypes()[0];
 899   
                     if (parameterType.isArray()) {
 900   
                         Object objArray = asPrimitiveArray(list, parameterType);
 901   
                         doMethodInvoke(object, metaMethod, new Object[]{
 902   
                             objArray
 903   
                         });
 904   
                         return;
 905   
                     }
 906   
                 }
 907   
                 
 908   
                 // if value is an multidimensional array  
 909   
                 if (newValue.getClass().isArray()) {
 910   
                     List list = Arrays.asList((Object[])newValue);
 911   
                     
 912   
                     Class parameterType = method.getParameterTypes()[0];
 913   
                     Class arrayType = parameterType.getComponentType();
 914   
                     Object objArray = Array.newInstance(arrayType, list.size());
 915   
                     
 916   
                     for (int i = 0; i < list.size(); i++) {
 917   
                         List list2 =Arrays.asList((Object[]) list.get(i));
 918   
                         Object objArray2 = asPrimitiveArray(list2, arrayType);
 919   
                         Array.set(objArray, i, objArray2);
 920   
                     }
 921   
 
 922   
                     doMethodInvoke(object, metaMethod, new Object[]{
 923   
                         objArray
 924   
                     });
 925   
                     return;
 926   
                 }
 927   
                 
 928   
                 throw new MissingPropertyException(property, theClass, e);
 929   
             }
 930   
             return;
 931   
         }
 932   
         */
 933   
         
 934  0
         MetaProperty mp = (MetaProperty) propertyMap.get(property);
 935  0
         if(mp != null) {
 936  0
             try {
 937  0
                 mp.setProperty(object, newValue);
 938  0
                 return;
 939   
             }
 940   
             catch(ReadOnlyPropertyException e) {
 941   
                 // just rethrow it; there's nothing left to do here
 942  0
                 throw e;
 943   
             }
 944   
             catch (Exception e) {
 945   
                 // if the value is a List see if we can construct the value
 946   
                 // from a constructor
 947  0
                 if (newValue == null)
 948  0
                     return;
 949  0
                 if (newValue instanceof List) {
 950  0
                     List list = (List) newValue;
 951  0
                     int params = list.size();
 952  0
                     Constructor[] constructors = mp.getType().getConstructors();
 953  0
                     for (int i = 0; i < constructors.length; i++) {
 954  0
                         Constructor constructor = constructors[i];
 955  0
                         if (constructor.getParameterTypes().length == params) {
 956  0
                             Object value = doConstructorInvoke(constructor, list.toArray());
 957  0
                             mp.setProperty(object, value);
 958  0
                             return;
 959   
                         }
 960   
                     }
 961   
                     
 962   
                     // if value is an array  
 963  0
                     Class parameterType = mp.getType();
 964  0
                     if (parameterType.isArray()) {
 965  0
                         Object objArray = asPrimitiveArray(list, parameterType);
 966  0
                         mp.setProperty(object, objArray);
 967  0
                         return;
 968   
                     }
 969   
                 }
 970   
 
 971   
                 // if value is an multidimensional array  
 972   
                 // jes currently this logic only supports metabeansproperties and
 973   
                 // not metafieldproperties. It shouldn't be too hard to support
 974   
                 // the latter...
 975  0
                 if (newValue.getClass().isArray() && mp instanceof MetaBeanProperty) {
 976  0
                     MetaBeanProperty mbp = (MetaBeanProperty) mp;
 977  0
                     List list = Arrays.asList((Object[])newValue);
 978  0
                     MetaMethod setter = mbp.getSetter();
 979   
                     
 980  0
                     Class parameterType = setter.getParameterTypes()[0];
 981  0
                     Class arrayType = parameterType.getComponentType();
 982  0
                     Object objArray = Array.newInstance(arrayType, list.size());
 983   
                     
 984  0
                     for (int i = 0; i < list.size(); i++) {
 985  0
                         List list2 =Arrays.asList((Object[]) list.get(i));
 986  0
                         Object objArray2 = asPrimitiveArray(list2, arrayType);
 987  0
                         Array.set(objArray, i, objArray2);
 988   
                     }
 989   
 
 990  0
                     doMethodInvoke(object, setter, new Object[]{
 991   
                         objArray
 992   
                     });
 993  0
                     return;
 994   
                 }
 995   
                 
 996  0
                 throw new MissingPropertyException(property, theClass, e);
 997   
             }
 998   
         }
 999   
         
 1000  0
         try {
 1001  0
             MetaMethod addListenerMethod = (MetaMethod) listeners.get(property);
 1002  0
             if (addListenerMethod != null && newValue instanceof Closure) {
 1003   
                 // lets create a dynamic proxy
 1004  0
                 Object proxy =
 1005   
                     createListenerProxy(addListenerMethod.getParameterTypes()[0], property, (Closure) newValue);
 1006  0
                 doMethodInvoke(object, addListenerMethod, new Object[] { proxy });
 1007  0
                 return;
 1008   
             }
 1009   
 
 1010  0
             if (genericSetMethod == null) {
 1011   
                 // Make sure there isn't a generic method in the "use" cases
 1012  0
                 List possibleGenericMethods = getMethods("set");
 1013  0
                 if (possibleGenericMethods != null) {
 1014  0
                     for (Iterator i = possibleGenericMethods.iterator(); i.hasNext(); ) {
 1015  0
                         MetaMethod mmethod = (MetaMethod) i.next();
 1016  0
                         Class[] paramTypes = mmethod.getParameterTypes();
 1017  0
                         if (paramTypes.length == 2 && paramTypes[0] == String.class) {
 1018  0
                             Object[] arguments = {property, newValue};
 1019  0
                             Object answer = doMethodInvoke(object, mmethod, arguments);
 1020  0
                             return;
 1021   
                         }
 1022   
                     }
 1023   
                 }
 1024   
             } 
 1025   
             else {
 1026  0
                 Object[] arguments = { property, newValue };
 1027  0
                 doMethodInvoke(object, genericSetMethod, arguments);
 1028  0
                 return;
 1029   
             }
 1030   
 
 1031   
             /** todo or are we an extensible class? */
 1032   
 
 1033   
             // lets try invoke the set method
 1034   
             // this is kind of ugly: if it is a protected field, we fall
 1035   
             // all the way down to this klunky code. Need a better
 1036   
             // way to handle this situation...
 1037   
 
 1038  0
             String method = "set" + capitalize(property);
 1039  0
             try {
 1040  0
                 invokeMethod(object, method, new Object[] { newValue });
 1041   
             }
 1042   
             catch (MissingMethodException e1) {
 1043  0
                 try {
 1044  0
                     Field field = object.getClass().getDeclaredField(property);
 1045  0
                     field.set(object, newValue);
 1046   
                 }
 1047   
                 catch (Exception e2) {
 1048  0
                     throw new MissingPropertyException(property, theClass, e2);
 1049   
                 }
 1050   
             }
 1051   
             
 1052   
         }
 1053   
         catch (GroovyRuntimeException e) {
 1054  0
             throw new MissingPropertyException(property, theClass, e);
 1055   
         }
 1056   
         
 1057   
         // if we got here, the damn thing just aint there...
 1058  0
         throw new MissingPropertyException(property, theClass);
 1059   
     }
 1060   
 
 1061   
     /**
 1062   
      * @param list
 1063   
      * @param parameterType
 1064   
      * @return
 1065   
      */
 1066  0
     private Object asPrimitiveArray(List list, Class parameterType) {
 1067  0
         Class arrayType = parameterType.getComponentType();
 1068  0
         Object objArray = Array.newInstance(arrayType, list.size());
 1069  0
         for (int i = 0; i < list.size(); i++) {
 1070  0
             Object obj = list.get(i);
 1071  0
             if (arrayType.isPrimitive()) {
 1072  0
                 if (obj instanceof Integer) {
 1073  0
                     Array.setInt(objArray, i, ((Integer) obj).intValue());
 1074   
                 }
 1075  0
                 else if (obj instanceof Double) {
 1076  0
                     Array.setDouble(objArray, i, ((Double) obj).doubleValue());
 1077   
                 }
 1078  0
                 else if (obj instanceof Boolean) {
 1079  0
                     Array.setBoolean(objArray, i, ((Boolean) obj).booleanValue());
 1080   
                 }
 1081  0
                 else if (obj instanceof Long) {
 1082  0
                     Array.setLong(objArray, i, ((Long) obj).longValue());
 1083   
                 }
 1084  0
                 else if (obj instanceof Float) {
 1085  0
                     Array.setFloat(objArray, i, ((Float) obj).floatValue());
 1086   
                 }
 1087  0
                 else if (obj instanceof Character) {
 1088  0
                     Array.setChar(objArray, i, ((Character) obj).charValue());
 1089   
                 }
 1090  0
                 else if (obj instanceof Byte) {
 1091  0
                     Array.setByte(objArray, i, ((Byte) obj).byteValue());
 1092   
                 }
 1093  0
                 else if (obj instanceof Short) {
 1094  0
                     Array.setShort(objArray, i, ((Short) obj).shortValue());
 1095   
                 }
 1096   
             }
 1097   
             else {
 1098  0
                 Array.set(objArray, i, obj);
 1099   
             }
 1100   
         }
 1101  0
         return objArray;
 1102   
     }
 1103   
     
 1104  0
     public ClassNode getClassNode() {
 1105  0
         if (classNode == null && GroovyObject.class.isAssignableFrom(theClass)) {
 1106   
             // lets try load it from the classpath
 1107  0
             String className = theClass.getName();
 1108  0
             String groovyFile = className;
 1109  0
             int idx = groovyFile.indexOf('$');
 1110  0
             if (idx > 0) {
 1111  0
                 groovyFile = groovyFile.substring(0, idx);
 1112   
             }
 1113  0
             groovyFile = groovyFile.replace('.', '/') + ".groovy";
 1114   
 
 1115   
             //System.out.println("Attempting to load: " + groovyFile);
 1116  0
             URL url = theClass.getClassLoader().getResource(groovyFile);
 1117  0
             if (url == null) {
 1118  0
                 url = Thread.currentThread().getContextClassLoader().getResource(groovyFile);
 1119   
             }
 1120  0
             if (url != null) {
 1121  0
                 try {
 1122   
 
 1123   
                     /**
 1124   
                      * todo there is no CompileUnit in scope so class name
 1125   
                      * checking won't work but that mostly affects the bytecode
 1126   
                      * generation rather than viewing the AST
 1127   
                      */
 1128   
 
 1129  0
                     CompilationUnit.ClassgenCallback search = new CompilationUnit.ClassgenCallback() {
 1130  0
                         public void call( ClassVisitor writer, ClassNode node ) {
 1131  0
                             if( node.getName().equals(theClass.getName()) ) {
 1132  0
                                 MetaClass.this.classNode = node;
 1133   
                             }
 1134   
                         }
 1135   
                     };
 1136   
                     
 1137   
                     
 1138  0
                     CompilationUnit unit = new CompilationUnit( getClass().getClassLoader() );
 1139  0
                     unit.setClassgenCallback( search );
 1140  0
                     unit.addSource( url );
 1141  0
                     unit.compile( Phases.CLASS_GENERATION );
 1142   
                 }
 1143   
                 catch (Exception e) {
 1144  0
                     throw new GroovyRuntimeException("Exception thrown parsing: " + groovyFile + ". Reason: " + e, e);
 1145   
                 }
 1146   
             }
 1147   
 
 1148   
         }
 1149  0
         return classNode;
 1150   
     }
 1151   
 
 1152  0
     public String toString() {
 1153  0
         return super.toString() + "[" + theClass + "]";
 1154   
     }
 1155   
 
 1156   
     // Implementation methods
 1157   
     //-------------------------------------------------------------------------
 1158   
 
 1159   
     /**
 1160   
      * Converts the given object into an array; if its an array then just cast
 1161   
      * otherwise wrap it in an array
 1162   
      */
 1163  0
     protected Object[] asArray(Object arguments) {
 1164  0
         if (arguments == null) {
 1165  0
             return EMPTY_ARRAY;
 1166   
         }
 1167  0
         if (arguments instanceof Tuple) {
 1168  0
             Tuple tuple = (Tuple) arguments;
 1169  0
             return tuple.toArray();
 1170   
         }
 1171  0
         if (arguments instanceof Object[]) {
 1172  0
             return (Object[]) arguments;
 1173   
         }
 1174   
         else {
 1175  0
             return new Object[] { arguments };
 1176   
         }
 1177   
     }
 1178   
     
 1179   
     /**
 1180   
      * @param listenerType
 1181   
      *            the interface of the listener to proxy
 1182   
      * @param listenerMethodName
 1183   
      *            the name of the method in the listener API to call the
 1184   
      *            closure on
 1185   
      * @param closure
 1186   
      *            the closure to invoke on the listenerMethodName method
 1187   
      *            invocation
 1188   
      * @return a dynamic proxy which calls the given closure on the given
 1189   
      *         method name
 1190   
      */
 1191  0
     protected Object createListenerProxy(Class listenerType, final String listenerMethodName, final Closure closure) {
 1192  0
         InvocationHandler handler = new ClosureListener(listenerMethodName, closure);
 1193  0
         return Proxy.newProxyInstance(listenerType.getClassLoader(), new Class[] { listenerType }, handler);
 1194   
     }
 1195   
 
 1196   
     /**
 1197   
      * Adds all the methods declared in the given class to the metaclass
 1198   
      * ignoring any matching methods already defined by a derived class
 1199   
      * 
 1200   
      * @param theClass
 1201   
      */
 1202  0
     protected void addMethods(Class theClass) {
 1203  0
         Method[] methodArray = theClass.getDeclaredMethods();
 1204  0
         for (int i = 0; i < methodArray.length; i++) {
 1205  0
             Method reflectionMethod = methodArray[i];
 1206  0
             if ( reflectionMethod.getName().indexOf('+') >= 0 ) {
 1207  0
                 continue;
 1208   
             }
 1209  0
             MetaMethod method = createMetaMethod(reflectionMethod);
 1210  0
             addMethod(method);
 1211   
         }
 1212   
     }
 1213   
 
 1214  0
     protected void addMethod(MetaMethod method) {
 1215  0
         String name = method.getName();
 1216   
 
 1217   
         //System.out.println(theClass.getName() + " == " + name + Arrays.asList(method.getParameterTypes()));
 1218   
 
 1219  0
         if (isGenericGetMethod(method) && genericGetMethod == null) {
 1220  0
             genericGetMethod = method;
 1221   
         }
 1222  0
         else if (isGenericSetMethod(method) && genericSetMethod == null) {
 1223  0
             genericSetMethod = method;
 1224   
         }
 1225  0
         if (method.isStatic()) {
 1226  0
             List list = (List) staticMethodIndex.get(name);
 1227  0
             if (list == null) {
 1228  0
                 list = new ArrayList();
 1229  0
                 staticMethodIndex.put(name, list);
 1230  0
                 list.add(method);
 1231   
             }
 1232   
             else {
 1233  0
                 if (!containsMatchingMethod(list, method)) {
 1234  0
                     list.add(method);
 1235   
                 }
 1236   
             }
 1237   
         }
 1238   
 
 1239  0
         List list = (List) methodIndex.get(name);
 1240  0
         if (list == null) {
 1241  0
             list = new ArrayList();
 1242  0
             methodIndex.put(name, list);
 1243  0
             list.add(method);
 1244   
         }
 1245   
         else {
 1246  0
             if (!containsMatchingMethod(list, method)) {
 1247  0
                 list.add(method);
 1248   
             }
 1249   
         }
 1250   
     }
 1251   
 
 1252   
     /**
 1253   
      * @return true if a method of the same matching prototype was found in the
 1254   
      *         list
 1255   
      */
 1256  0
     protected boolean containsMatchingMethod(List list, MetaMethod method) {
 1257  0
         for (Iterator iter = list.iterator(); iter.hasNext();) {
 1258  0
             MetaMethod aMethod = (MetaMethod) iter.next();
 1259  0
             Class[] params1 = aMethod.getParameterTypes();
 1260  0
             Class[] params2 = method.getParameterTypes();
 1261  0
             if (params1.length == params2.length) {
 1262  0
                 boolean matches = true;
 1263  0
                 for (int i = 0; i < params1.length; i++) {
 1264  0
                     if (params1[i] != params2[i]) {
 1265  0
                         matches = false;
 1266  0
                         break;
 1267   
                     }
 1268   
                 }
 1269  0
                 if (matches) {
 1270  0
                     return true;
 1271   
                 }
 1272   
             }
 1273   
         }
 1274  0
         return false;
 1275   
     }
 1276   
 
 1277   
     /**
 1278   
      * Adds all of the newly defined methods from the given class to this
 1279   
      * metaclass
 1280   
      * 
 1281   
      * @param theClass
 1282   
      */
 1283  0
     protected void addNewStaticMethodsFrom(Class theClass) {
 1284  0
         MetaClass interfaceMetaClass = registry.getMetaClass(theClass);
 1285  0
         Iterator iter = interfaceMetaClass.newGroovyMethodsList.iterator();
 1286  0
         while (iter.hasNext()) {
 1287  0
             MetaMethod method = (MetaMethod) iter.next();
 1288  0
             addMethod(method);
 1289  0
             newGroovyMethodsList.add(method);
 1290   
         }
 1291   
     }
 1292   
 
 1293   
     /**
 1294   
      * @return the value of the static property of the given class
 1295   
      */
 1296  0
     protected Object getStaticProperty(Class aClass, String property) {
 1297   
         //System.out.println("Invoking property: " + property + " on class: "
 1298   
         // + aClass);
 1299   
 
 1300  0
         Exception lastException = null;
 1301  0
         try {
 1302  0
             Field field = aClass.getField(property);
 1303  0
             if (field != null) {
 1304  0
                 if ((field.getModifiers() & Modifier.STATIC) != 0) {
 1305  0
                     return field.get(null);
 1306   
                 }
 1307   
             }
 1308   
         }
 1309   
         catch (Exception e) {
 1310  0
             lastException = e;
 1311   
         }
 1312   
 
 1313   
         // lets try invoke a static getter method
 1314  0
         try {
 1315  0
             MetaMethod method = findStaticGetter(aClass, "get" + capitalize(property));
 1316  0
             if (method != null) {
 1317  0
                 return doMethodInvoke(aClass, method, EMPTY_ARRAY);
 1318   
             }
 1319   
         }
 1320   
         catch (GroovyRuntimeException e) {
 1321  0
             throw new MissingPropertyException(property, aClass, e);
 1322   
         }
 1323   
 
 1324  0
         if (lastException == null) {
 1325  0
             throw new MissingPropertyException(property, aClass);
 1326   
         }
 1327   
         else {
 1328  0
             throw new MissingPropertyException(property, aClass, lastException);
 1329   
         }
 1330   
     }
 1331   
 
 1332   
     /**
 1333   
      * @return the matching method which should be found
 1334   
      */
 1335  0
     protected MetaMethod findMethod(Method aMethod) {
 1336  0
         List methods = getMethods(aMethod.getName());
 1337  0
         for (Iterator iter = methods.iterator(); iter.hasNext();) {
 1338  0
             MetaMethod method = (MetaMethod) iter.next();
 1339  0
             if (method.isMethod(aMethod)) {
 1340  0
                 return method;
 1341   
             }
 1342   
         }
 1343   
         //log.warning("Creating reflection based dispatcher for: " + aMethod);
 1344  0
         return new ReflectionMetaMethod(aMethod);
 1345   
     }
 1346   
 
 1347   
     /**
 1348   
      * @return the getter method for the given object
 1349   
      */
 1350  0
     protected MetaMethod findGetter(Object object, String name) {
 1351  0
         List methods = getMethods(name);
 1352  0
         for (Iterator iter = methods.iterator(); iter.hasNext();) {
 1353  0
             MetaMethod method = (MetaMethod) iter.next();
 1354  0
             if (method.getParameterTypes().length == 0) {
 1355  0
                 return method;
 1356   
             }
 1357   
         }
 1358  0
         return null;
 1359   
     }
 1360   
 
 1361   
     /**
 1362   
      * @return the Method of the given name with no parameters or null
 1363   
      */
 1364  0
     protected MetaMethod findStaticGetter(Class type, String name) {
 1365  0
         List methods = getStaticMethods(name);
 1366  0
         for (Iterator iter = methods.iterator(); iter.hasNext();) {
 1367  0
             MetaMethod method = (MetaMethod) iter.next();
 1368  0
             if (method.getParameterTypes().length == 0) {
 1369  0
                 return method;
 1370   
             }
 1371   
         }
 1372   
 
 1373   
         /** todo dirty hack - don't understand why this code is necessary - all methods should be in the allMethods list! */
 1374  0
         try {
 1375  0
             Method method = type.getMethod(name, EMPTY_TYPE_ARRAY);
 1376  0
             if ((method.getModifiers() & Modifier.STATIC) != 0) {
 1377  0
                 return findMethod(method);
 1378   
             }
 1379   
             else {
 1380  0
                 return null;
 1381   
             }
 1382   
         }
 1383   
         catch (Exception e) {
 1384  0
             return null;
 1385   
         }
 1386   
     }
 1387   
 
 1388  0
     protected Object doMethodInvoke(Object object, MetaMethod method, Object[] argumentArray) {
 1389   
         //System.out.println("Evaluating method: " + method);
 1390   
         //System.out.println("on object: " + object + " with arguments: " +
 1391   
         // InvokerHelper.toString(argumentArray));
 1392   
         //System.out.println(this.theClass);
 1393   
 
 1394  0
         try {
 1395  0
             if (argumentArray == null) {
 1396  0
                 argumentArray = EMPTY_ARRAY;
 1397   
             }
 1398  0
             else if (method.getParameterTypes().length == 1 && argumentArray.length == 0) {
 1399  0
                 argumentArray = ARRAY_WITH_NULL;
 1400   
             }
 1401  0
             return method.invoke(object, argumentArray);
 1402   
         }
 1403   
         catch (ClassCastException e) {
 1404  0
             if (coerceGStrings(argumentArray)) {
 1405  0
                 try {
 1406  0
                     return doMethodInvoke(object, method, argumentArray);
 1407   
                 }
 1408   
                 catch (Exception e2) {
 1409   
                     // allow fall through
 1410   
                 }
 1411   
             }
 1412  0
             throw new GroovyRuntimeException(
 1413   
                 "failed to invoke method: "
 1414   
                     + method
 1415   
                     + " on: "
 1416   
                     + object
 1417   
                     + " with arguments: "
 1418   
                     + InvokerHelper.toString(argumentArray)
 1419   
                     + " reason: "
 1420   
                     + e,
 1421   
                 e);
 1422   
         }
 1423   
         catch (InvocationTargetException e) {
 1424  0
             Throwable t = e.getTargetException();
 1425  0
             if (t instanceof Error) {
 1426  0
                 Error error = (Error) t;
 1427  0
                 throw error;
 1428   
             }
 1429  0
             if (t instanceof RuntimeException) {
 1430  0
                 RuntimeException runtimeEx = (RuntimeException) t;
 1431  0
                 throw runtimeEx;
 1432   
             }
 1433  0
             throw new InvokerInvocationException(e);
 1434   
         }
 1435   
         catch (IllegalAccessException e) {
 1436  0
             throw new GroovyRuntimeException(
 1437   
                 "could not access method: "
 1438   
                     + method
 1439   
                     + " on: "
 1440   
                     + object
 1441   
                     + " with arguments: "
 1442   
                     + InvokerHelper.toString(argumentArray)
 1443   
                     + " reason: "
 1444   
                     + e,
 1445   
                 e);
 1446   
         }
 1447   
         catch (IllegalArgumentException e) {
 1448  0
             if (coerceGStrings(argumentArray)) {
 1449  0
                 try {
 1450  0
                     return doMethodInvoke(object, method, argumentArray);
 1451   
                 }
 1452   
                 catch (Exception e2) {
 1453   
                     // allow fall through
 1454   
                 }
 1455   
             }
 1456  0
             Object[] args = coerceNumbers(method, argumentArray);
 1457  0
             if (args != null) {
 1458  0
                 try {
 1459  0
                     return doMethodInvoke(object, method, args);
 1460   
                 }
 1461   
                 catch (Exception e3) {
 1462   
                     // allow fall through
 1463   
                 }
 1464   
             }
 1465   
 
 1466  0
             throw new GroovyRuntimeException(
 1467   
                     "failed to invoke method: "
 1468   
                     + method
 1469   
                     + " on: "
 1470   
                     + object
 1471   
                     + " with arguments: "
 1472   
                     + InvokerHelper.toString(argumentArray)
 1473   
                     + " reason: "
 1474   
                     + e,
 1475   
                     e);
 1476   
         }
 1477   
         catch (RuntimeException e) {
 1478  0
             throw e;
 1479   
         }
 1480   
         catch (Exception e) {
 1481  0
             throw new GroovyRuntimeException(
 1482   
                 "failed to invoke method: "
 1483   
                     + method
 1484   
                     + " on: "
 1485   
                     + object
 1486   
                     + " with arguments: "
 1487   
                     + InvokerHelper.toString(argumentArray)
 1488   
                     + " reason: "
 1489   
                     + e,
 1490   
                 e);
 1491   
         }
 1492   
     }
 1493   
 
 1494  0
     private static Object[] coerceNumbers(MetaMethod method, Object[] arguments) {
 1495  0
         Object[] ans = null;
 1496  0
         boolean coerced = false; // to indicate that at least one param is coerced
 1497   
 
 1498  0
         Class[] params = method.getParameterTypes();
 1499   
 
 1500  0
         if (params.length != arguments.length) {
 1501  0
             return null;
 1502   
         }
 1503   
 
 1504  0
         ans = new Object[arguments.length];
 1505   
 
 1506  0
         for (int i = 0, size = arguments.length; i < size; i++) {
 1507  0
             Object argument = arguments[i];
 1508  0
             Class param = params[i];
 1509  0
             if ((Number.class.isAssignableFrom(param) || param.isPrimitive()) && argument instanceof Number) { // Number types
 1510  0
                 if (param == Byte.class || param == Byte.TYPE ) {
 1511  0
                     ans[i] = new Byte(((Number)argument).byteValue());
 1512  0
                     coerced = true; continue;
 1513   
                 }
 1514  0
                 if (param == Double.class || param == Double.TYPE) {
 1515  0
                     ans[i] = new Double(((Number)argument).doubleValue());
 1516  0
                     coerced = true; continue;
 1517   
                 }
 1518  0
                 if (param == Float.class || param == Float.TYPE) {
 1519  0
                     ans[i] = new Float(((Number)argument).floatValue());
 1520  0
                     coerced = true; continue;
 1521   
                 }
 1522  0
                 if (param == Integer.class || param == Integer.TYPE) {
 1523  0
                     ans[i] = new Integer(((Number)argument).intValue());
 1524  0
                     coerced = true; continue;
 1525   
                 }
 1526  0
                 if (param == Long.class || param == Long.TYPE) {
 1527  0
                     ans[i] = new Long(((Number)argument).longValue());
 1528  0
                     coerced = true; continue;
 1529   
                 }
 1530  0
                 if (param == Short.class || param == Short.TYPE) {
 1531  0
                     ans[i] = new Short(((Number)argument).shortValue());
 1532  0
                     coerced = true; continue;
 1533   
                 }
 1534  0
                 if (param == BigDecimal.class ) {
 1535  0
                     ans[i] = new BigDecimal(((Number)argument).doubleValue());
 1536  0
                     coerced = true; continue;
 1537   
                 }
 1538  0
                 if (param == BigInteger.class) {
 1539  0
                     ans[i] = new BigInteger(String.valueOf(((Number)argument).longValue()));
 1540  0
                     coerced = true; continue;
 1541   
                 }
 1542   
             }
 1543  0
             else if (param.isArray() && argument.getClass().isArray()) {
 1544  0
                 Class paramElem = param.getComponentType();
 1545  0
                 if (paramElem.isPrimitive()) {
 1546  0
                     if (paramElem == boolean.class && argument.getClass().getName().equals("[Ljava.lang.Boolean;")) {
 1547  0
                         ans[i] = InvokerHelper.convertToBooleanArray(argument);
 1548  0
                         coerced = true;
 1549  0
                         continue;
 1550   
                     }
 1551  0
                     if (paramElem == byte.class && argument.getClass().getName().equals("[Ljava.lang.Byte;")) {
 1552  0
                         ans[i] = InvokerHelper.convertToByteArray(argument);
 1553  0
                         coerced = true;
 1554  0
                         continue;
 1555   
                     }
 1556  0
                     if (paramElem == char.class && argument.getClass().getName().equals("[Ljava.lang.Character;")) {
 1557  0
                         ans[i] = InvokerHelper.convertToCharArray(argument);
 1558  0
                         coerced = true;
 1559  0
                         continue;
 1560   
                     }
 1561  0
                     if (paramElem == short.class && argument.getClass().getName().equals("[Ljava.lang.Short;")) {
 1562  0
                         ans[i] = InvokerHelper.convertToShortArray(argument);
 1563  0
                         coerced = true;
 1564  0
                         continue;
 1565   
                     }
 1566  0
                     if (paramElem == int.class && argument.getClass().getName().equals("[Ljava.lang.Integer;")) {
 1567  0
                         ans[i] = InvokerHelper.convertToIntArray(argument);
 1568  0
                         coerced = true;
 1569  0
                         continue;
 1570   
                     }
 1571  0
                     if (paramElem == long.class
 1572   
                             && argument.getClass().getName().equals("[Ljava.lang.Long;")
 1573   
                             && argument.getClass().getName().equals("[Ljava.lang.Integer;")
 1574   
                                                             ) {
 1575  0
                         ans[i] = InvokerHelper.convertToLongArray(argument);
 1576  0
                         coerced = true;
 1577  0
                         continue;
 1578   
                     }
 1579  0
                     if (paramElem == float.class
 1580   
                             && argument.getClass().getName().equals("[Ljava.lang.Float;")
 1581   
                             && argument.getClass().getName().equals("[Ljava.lang.Integer;")
 1582   
                                                             ) {
 1583  0
                         ans[i] = InvokerHelper.convertToFloatArray(argument);
 1584  0
                         coerced = true;
 1585  0
                         continue;
 1586   
                     }
 1587  0
                     if (paramElem == double.class &&
 1588   
                             argument.getClass().getName().equals("[Ljava.lang.Double;") &&
 1589   
                             argument.getClass().getName().equals("[Ljava.lang.BigDecimal;") &&
 1590   
                             argument.getClass().getName().equals("[Ljava.lang.Float;")) {
 1591  0
                         ans[i] = InvokerHelper.convertToDoubleArray(argument);
 1592  0
                         coerced = true;
 1593  0
                         continue;
 1594   
                     }
 1595   
                 }
 1596   
             }
 1597   
         }
 1598  0
         return coerced ? ans : null;
 1599   
     }
 1600   
 
 1601  0
     protected Object doConstructorInvoke(Constructor constructor, Object[] argumentArray) {
 1602   
         //System.out.println("Evaluating constructor: " + constructor + " with
 1603   
         // arguments: " + InvokerHelper.toString(argumentArray));
 1604   
         //System.out.println(this.theClass);
 1605   
 
 1606  0
         try {
 1607   
             // the following patch was provided by Mori Kouhei to fix JIRA 435
 1608   
             /* but it opens the ctor up to everyone, so it is no longer private!
 1609   
             final Constructor ctor = constructor;
 1610   
             AccessController.doPrivileged(new PrivilegedAction() {
 1611   
                 public Object run() {
 1612   
                     ctor.setAccessible(ctor.getDeclaringClass().equals(theClass));
 1613   
                     return null;
 1614   
                 }
 1615   
             });
 1616   
             */
 1617   
             // end of patch
 1618   
 
 1619  0
             return constructor.newInstance(argumentArray);
 1620   
         }
 1621   
         catch (InvocationTargetException e) {
 1622  0
             Throwable t = e.getTargetException();
 1623  0
             if (t instanceof Error) {
 1624  0
                 Error error = (Error) t;
 1625  0
                 throw error;
 1626   
             }
 1627  0
             if (t instanceof RuntimeException) {
 1628  0
                 RuntimeException runtimeEx = (RuntimeException) t;
 1629  0
                 throw runtimeEx;
 1630   
             }
 1631  0
             throw new InvokerInvocationException(e);
 1632   
         }
 1633   
         catch (IllegalArgumentException e) {
 1634  0
             if (coerceGStrings(argumentArray)) {
 1635  0
                 try {
 1636  0
                     return constructor.newInstance(argumentArray);
 1637   
                 }
 1638   
                 catch (Exception e2) {
 1639   
                     // allow fall through
 1640   
                 }
 1641   
             }
 1642  0
             throw new GroovyRuntimeException(
 1643   
                 "failed to invoke constructor: "
 1644   
                     + constructor
 1645   
                     + " with arguments: "
 1646   
                     + InvokerHelper.toString(argumentArray)
 1647   
                     + " reason: "
 1648   
                     + e,
 1649   
                 e);
 1650   
         }
 1651   
         catch (IllegalAccessException e) {
 1652  0
             throw new GroovyRuntimeException(
 1653   
                 "could not access constructor: "
 1654   
                     + constructor
 1655   
                     + " with arguments: "
 1656   
                     + InvokerHelper.toString(argumentArray)
 1657   
                     + " reason: "
 1658   
                     + e,
 1659   
                 e);
 1660   
         }
 1661   
         catch (Exception e) {
 1662  0
             throw new GroovyRuntimeException(
 1663   
                 "failed to invoke constructor: "
 1664   
                     + constructor
 1665   
                     + " with arguments: "
 1666   
                     + InvokerHelper.toString(argumentArray)
 1667   
                     + " reason: "
 1668   
                     + e,
 1669   
                 e);
 1670   
         }
 1671   
     }
 1672   
 
 1673   
     /**
 1674   
      * Chooses the correct method to use from a list of methods which match by
 1675   
      * name.
 1676   
      * 
 1677   
      * @param methods
 1678   
      *            the possible methods to choose from
 1679   
      * @param arguments
 1680   
      *            the original argument to the method
 1681   
      * @return
 1682   
      */
 1683  0
     protected Object chooseMethod(String methodName, List methods, Class[] arguments, boolean coerce) {
 1684  0
         int methodCount = methods.size();
 1685  0
         if (methodCount <= 0) {
 1686  0
             return null;
 1687   
         }
 1688  0
         else if (methodCount == 1) {
 1689  0
             Object method = methods.get(0);
 1690  0
             if (isValidMethod(method, arguments, coerce)) {
 1691  0
                 return method;
 1692   
             }
 1693  0
             return null;
 1694   
         }
 1695  0
         Object answer = null;
 1696  0
         if (arguments == null || arguments.length == 0) {
 1697  0
             answer = chooseEmptyMethodParams(methods);
 1698   
         }
 1699  0
         else if (arguments.length == 1 && arguments[0] == null) {
 1700  0
             answer = chooseMostGeneralMethodWith1NullParam(methods);
 1701   
         }
 1702   
         else {
 1703  0
             List matchingMethods = new ArrayList();
 1704   
 
 1705  0
             for (Iterator iter = methods.iterator(); iter.hasNext();) {
 1706  0
                 Object method = iter.next();
 1707  0
                 Class[] paramTypes;
 1708   
 
 1709   
                 // making this false helps find matches
 1710  0
                 if (isValidMethod(method, arguments, coerce)) {
 1711  0
                     matchingMethods.add(method);
 1712   
                 }
 1713   
             }
 1714  0
             if (matchingMethods.isEmpty()) {
 1715  0
                 return null;
 1716   
             }
 1717  0
             else if (matchingMethods.size() == 1) {
 1718  0
                 return matchingMethods.get(0);
 1719   
             }
 1720  0
             return chooseMostSpecificParams(methodName, matchingMethods, arguments);
 1721   
 
 1722   
         }
 1723  0
         if (answer != null) {
 1724  0
             return answer;
 1725   
         }
 1726  0
         throw new GroovyRuntimeException(
 1727   
             "Could not find which method to invoke from this list: "
 1728   
                 + methods
 1729   
                 + " for arguments: "
 1730   
                 + InvokerHelper.toString(arguments));
 1731   
     }
 1732   
 
 1733  0
     protected boolean isValidMethod(Object method, Class[] arguments, boolean includeCoerce) {
 1734  0
         Class[] paramTypes = getParameterTypes(method);
 1735  0
         return isValidMethod(paramTypes, arguments, includeCoerce);
 1736   
     }
 1737   
 
 1738  0
     public static boolean isValidMethod(Class[] paramTypes, Class[] arguments, boolean includeCoerce) {
 1739  0
         if (arguments == null) {
 1740  0
             return true;
 1741   
         }
 1742  0
         int size = arguments.length;
 1743  0
         boolean validMethod = false;
 1744  0
         if (paramTypes.length == size) {
 1745   
             // lets check the parameter types match
 1746  0
             validMethod = true;
 1747  0
             for (int i = 0; i < size; i++) {
 1748  0
                 if (!isCompatibleClass(paramTypes[i], arguments[i], includeCoerce)) {
 1749  0
                     validMethod = false;
 1750   
                 }
 1751   
             }
 1752   
         }
 1753   
         else {
 1754  0
             if (paramTypes.length == 1 && size == 0) {
 1755  0
                 return true;
 1756   
             }
 1757   
         }
 1758  0
         return validMethod;
 1759   
     }
 1760   
 
 1761  0
     protected Object chooseMostSpecificParams(String name, List matchingMethods, Class[] arguments) {
 1762  0
         for (Iterator iter = matchingMethods.iterator(); iter.hasNext();) {
 1763  0
             Object method = iter.next();
 1764  0
             Class[] paramTypes = getParameterTypes(method);
 1765  0
             if (Arrays.equals(arguments, paramTypes)) return method;
 1766   
         }
 1767  0
         Object answer = null;
 1768  0
         int size = arguments.length;
 1769  0
         Class[] mostSpecificTypes = null;
 1770  0
         for (Iterator iter = matchingMethods.iterator(); iter.hasNext();) {
 1771  0
             Object method = iter.next();
 1772  0
             Class[] paramTypes = getParameterTypes(method);
 1773  0
             if (answer == null) {
 1774  0
                 answer = method;
 1775  0
                 mostSpecificTypes = paramTypes;
 1776   
             }
 1777   
             else {
 1778  0
                 boolean useThisMethod = false;
 1779  0
                 for (int i = 0; i < size; i++) {
 1780  0
                     Class mostSpecificType = mostSpecificTypes[i];
 1781  0
                     Class type = paramTypes[i];
 1782   
 
 1783  0
                     if (!isAssignableFrom(mostSpecificType, type)) {
 1784   
 
 1785  0
                         useThisMethod = true;
 1786  0
                         break;
 1787   
                     }
 1788   
 
 1789   
                 }
 1790  0
                 if (useThisMethod) {
 1791   
 
 1792  0
                     if (size > 1) {
 1793  0
                         checkForInvalidOverloading(name, mostSpecificTypes, paramTypes);
 1794   
                     }
 1795   
 
 1796  0
                     answer = method;
 1797  0
                     mostSpecificTypes = paramTypes;
 1798   
                 }
 1799   
             }
 1800   
         }
 1801  0
         return answer;
 1802   
     }
 1803   
 
 1804   
     /**
 1805   
      * Checks that one of the parameter types is a superset of the other and
 1806   
      * that the two lists of types don't conflict. e.g. foo(String, Object) and
 1807   
      * foo(Object, String) would conflict if called with foo("a", "b").
 1808   
      * 
 1809   
      * Note that this method is only called with 2 possible signatures. i.e.
 1810   
      * possible invalid combinations will already have been filtered out. So if
 1811   
      * there were methods foo(String, Object) and foo(Object, String) then one
 1812   
      * of these would be already filtered out if foo was called as foo(12, "a")
 1813   
      */
 1814  0
     protected void checkForInvalidOverloading(String name, Class[] baseTypes, Class[] derivedTypes) {
 1815  0
         for (int i = 0, size = baseTypes.length; i < size; i++) {
 1816  0
             Class baseType = baseTypes[i];
 1817  0
             Class derivedType = derivedTypes[i];
 1818  0
             if (!isAssignableFrom(derivedType, baseType)) {
 1819  0
                 throw new GroovyRuntimeException(
 1820   
                     "Ambiguous method overloading for method: "
 1821   
                         + name
 1822   
                         + ". Cannot resolve which method to invoke due to overlapping prototypes between: "
 1823   
                         + InvokerHelper.toString(baseTypes)
 1824   
                         + " and: "
 1825   
                         + InvokerHelper.toString(derivedTypes));
 1826   
             }
 1827   
         }
 1828   
     }
 1829   
 
 1830  0
     protected Class[] getParameterTypes(Object methodOrConstructor) {
 1831  0
         if (methodOrConstructor instanceof MetaMethod) {
 1832  0
             MetaMethod method = (MetaMethod) methodOrConstructor;
 1833  0
             return method.getParameterTypes();
 1834   
         }
 1835  0
         if (methodOrConstructor instanceof Method) {
 1836  0
             Method method = (Method) methodOrConstructor;
 1837  0
             return method.getParameterTypes();
 1838   
         }
 1839  0
         if (methodOrConstructor instanceof Constructor) {
 1840  0
             Constructor constructor = (Constructor) methodOrConstructor;
 1841  0
             return constructor.getParameterTypes();
 1842   
         }
 1843  0
         throw new IllegalArgumentException("Must be a Method or Constructor");
 1844   
     }
 1845   
 
 1846   
     /**
 1847   
      * @return the method with 1 parameter which takes the most general type of
 1848   
      *         object (e.g. Object) ignoring primitve types
 1849   
      */
 1850  0
     protected Object chooseMostGeneralMethodWith1NullParam(List methods) {
 1851   
         // lets look for methods with 1 argument which matches the type of the
 1852   
         // arguments
 1853  0
         Class closestClass = null;
 1854  0
         Object answer = null;
 1855   
 
 1856  0
         for (Iterator iter = methods.iterator(); iter.hasNext();) {
 1857  0
             Object method = iter.next();
 1858  0
             Class[] paramTypes = getParameterTypes(method);
 1859  0
             int paramLength = paramTypes.length;
 1860  0
             if (paramLength == 1) {
 1861  0
                 Class theType = paramTypes[0];
 1862  0
                 if (theType.isPrimitive()) continue;
 1863  0
                 if (closestClass == null || isAssignableFrom(closestClass, theType)) {
 1864  0
                     closestClass = theType;
 1865  0
                     answer = method;
 1866   
                 }                
 1867   
             }
 1868   
         }
 1869  0
         return answer;
 1870   
     }
 1871   
 
 1872   
     /**
 1873   
      * @return the method with 1 parameter which takes the most general type of
 1874   
      *         object (e.g. Object)
 1875   
      */
 1876  0
     protected Object chooseEmptyMethodParams(List methods) {
 1877  0
         for (Iterator iter = methods.iterator(); iter.hasNext();) {
 1878  0
             Object method = iter.next();
 1879  0
             Class[] paramTypes = getParameterTypes(method);
 1880  0
             int paramLength = paramTypes.length;
 1881  0
             if (paramLength == 0) {
 1882  0
                 return method;
 1883   
             }
 1884   
         }
 1885  0
         return null;
 1886   
     }
 1887   
 
 1888  0
     protected static boolean isCompatibleInstance(Class type, Object value, boolean includeCoerce) {
 1889  0
         boolean answer = value == null || type.isInstance(value);
 1890  0
         if (!answer) {
 1891  0
             if (type.isPrimitive()) {
 1892  0
                 if (type == int.class) {
 1893  0
                     return value instanceof Integer;
 1894   
                 }
 1895  0
                 else if (type == double.class) {
 1896  0
                     return value instanceof Double || value instanceof Float || value instanceof Integer || value instanceof BigDecimal;
 1897   
                 }
 1898  0
                 else if (type == boolean.class) {
 1899  0
                     return value instanceof Boolean;
 1900   
                 }
 1901  0
                 else if (type == long.class) {
 1902  0
                     return value instanceof Long || value instanceof Integer;
 1903   
                 }
 1904  0
                 else if (type == float.class) {
 1905  0
                     return value instanceof Float || value instanceof Integer;
 1906   
                 }
 1907  0
                 else if (type == char.class) {
 1908  0
                     return value instanceof Character;
 1909   
                 }
 1910  0
                 else if (type == byte.class) {
 1911  0
                     return value instanceof Byte;
 1912   
                 }
 1913  0
                 else if (type == short.class) {
 1914  0
                     return value instanceof Short;
 1915   
                 }
 1916   
             }
 1917  0
             else if(type.isArray() && value.getClass().isArray()) {
 1918  0
                 return isCompatibleClass(type.getComponentType(), value.getClass().getComponentType(), false);
 1919   
             }
 1920  0
             else if (includeCoerce) {
 1921  0
                 if (type == String.class && value instanceof GString) {
 1922  0
                     return true;
 1923   
                 }
 1924  0
                 else if (value instanceof Number) {
 1925   
                     // lets allow numbers to be coerced downwards?
 1926  0
                     return Number.class.isAssignableFrom(type);
 1927   
                 }
 1928   
             }
 1929   
         }
 1930  0
         return answer;
 1931   
     }
 1932  0
     protected static boolean isCompatibleClass(Class type, Class value, boolean includeCoerce) {
 1933  0
         boolean answer = value == null || type.isAssignableFrom(value); // this might have taken care of primitive types, rendering part of the following code unnecessary
 1934  0
         if (!answer) {
 1935  0
             if (type.isPrimitive()) {
 1936  0
                 if (type == int.class) {
 1937  0
                     return value == Integer.class;// || value == BigDecimal.class; //br added BigDecimal
 1938   
                 }
 1939  0
                 else if (type == double.class) {
 1940  0
                     return value == Double.class || value == Float.class || value == Integer.class || value == BigDecimal.class;
 1941   
                 }
 1942  0
                 else if (type == boolean.class) {
 1943  0
                     return value == Boolean.class;
 1944   
                 }
 1945  0
                 else if (type == long.class) {
 1946  0
                     return value == Long.class || value == Integer.class; // || value == BigDecimal.class;//br added BigDecimal
 1947   
                 }
 1948  0
                 else if (type == float.class) {
 1949  0
                     return value == Float.class || value == Integer.class; // || value == BigDecimal.class;//br added BigDecimal
 1950   
                 }
 1951  0
                 else if (type == char.class) {
 1952  0
                     return value == Character.class;
 1953   
                 }
 1954  0
                 else if (type == byte.class) {
 1955  0
                     return value == Byte.class;
 1956   
                 }
 1957  0
                 else if (type == short.class) {
 1958  0
                     return value == Short.class;
 1959   
                 }
 1960   
             }
 1961  0
             else if(type.isArray() && value.isArray()) {
 1962  0
                 return isCompatibleClass(type.getComponentType(), value.getComponentType(), false);
 1963   
             }
 1964  0
             else if (includeCoerce) {
 1965   
 //if (type == String.class && value == GString.class) {
 1966  0
                 if (type == String.class && GString.class.isAssignableFrom(value)) {
 1967  0
                     return true;
 1968   
                 }
 1969  0
                 else if (value == Number.class) {
 1970   
                     // lets allow numbers to be coerced downwards?
 1971  0
                     return Number.class.isAssignableFrom(type);
 1972   
                 }
 1973   
             }
 1974   
         }
 1975  0
         return answer;
 1976   
     }
 1977   
 
 1978  0
     protected boolean isAssignableFrom(Class mostSpecificType, Class type) {
 1979   
         // let's handle primitives
 1980  0
         if (mostSpecificType.isPrimitive() && type.isPrimitive()) {
 1981  0
             if (mostSpecificType == type) {
 1982  0
                 return true;
 1983   
             }
 1984   
             else {  // note: there is not coercion for boolean and char. Range matters, precision doesn't
 1985  0
                 if (type == int.class) {
 1986  0
                     return
 1987   
                             mostSpecificType == int.class
 1988   
                             || mostSpecificType == short.class
 1989   
                             || mostSpecificType == byte.class;
 1990   
                 }
 1991  0
                 else if (type == double.class) {
 1992  0
                     return
 1993   
                             mostSpecificType == double.class
 1994   
                             || mostSpecificType == int.class
 1995   
                             || mostSpecificType == long.class
 1996   
                             || mostSpecificType == short.class
 1997   
                             || mostSpecificType == byte.class
 1998   
                             || mostSpecificType == float.class;
 1999   
                 }
 2000  0
                 else if (type == long.class) {
 2001  0
                     return
 2002   
                             mostSpecificType == long.class
 2003   
                             || mostSpecificType == int.class
 2004   
                             || mostSpecificType == short.class
 2005   
                             || mostSpecificType == byte.class;
 2006   
                 }
 2007  0
                 else if (type == float.class) {
 2008  0
                     return
 2009   
                             mostSpecificType == float.class
 2010   
                             || mostSpecificType == int.class
 2011   
                             || mostSpecificType == long.class
 2012   
                             || mostSpecificType == short.class
 2013   
                             || mostSpecificType == byte.class;
 2014   
                 }
 2015  0
                 else if (type == short.class) {
 2016  0
                     return
 2017   
                             mostSpecificType == short.class
 2018   
                             || mostSpecificType == byte.class;
 2019   
                 }
 2020   
                 else {
 2021  0
                     return false;
 2022   
                 }
 2023   
             }
 2024   
         }
 2025   
 
 2026  0
         boolean answer = type.isAssignableFrom(mostSpecificType);
 2027  0
         if (!answer) {
 2028  0
             answer = autoboxType(type).isAssignableFrom(autoboxType(mostSpecificType));
 2029   
         }
 2030  0
         return answer;
 2031   
     }
 2032   
 
 2033  0
     private Class autoboxType(Class type) {
 2034  0
         if (type.isPrimitive()) {
 2035  0
             if (type == int.class) {
 2036  0
                 return Integer.class;
 2037   
             }
 2038  0
             else if (type == double.class) {
 2039  0
                 return Double.class;
 2040   
             }
 2041  0
             else if (type == long.class) {
 2042  0
                 return Long.class;
 2043   
             }
 2044  0
             else if (type == boolean.class) {
 2045  0
                 return Boolean.class;
 2046   
             }
 2047  0
             else if (type == float.class) {
 2048  0
                 return Float.class;
 2049   
             }
 2050  0
             else if (type == char.class) {
 2051  0
                 return Character.class;
 2052   
             }
 2053  0
             else if (type == byte.class) {
 2054  0
                 return Byte.class;
 2055   
             }
 2056  0
             else if (type == short.class) {
 2057  0
                 return Short.class;
 2058   
             }
 2059   
         }
 2060  0
         return type;
 2061   
     }
 2062   
 
 2063   
     /**
 2064   
      * Coerces any GString instances into Strings
 2065   
      * 
 2066   
      * @return true if some coercion was done. 
 2067   
      */
 2068  0
     protected static boolean coerceGStrings(Object[] arguments) {
 2069  0
         boolean coerced = false;
 2070  0
         for (int i = 0, size = arguments.length; i < size; i++) {
 2071  0
             Object argument = arguments[i];
 2072  0
             if (argument instanceof GString) {
 2073  0
                 arguments[i] = argument.toString();
 2074  0
                 coerced = true;
 2075   
             }
 2076   
         }
 2077  0
         return coerced;
 2078   
     }
 2079   
 
 2080  0
     protected boolean isGenericSetMethod(MetaMethod method) {
 2081  0
         return (method.getName().equals("set"))
 2082   
             && method.getParameterTypes().length == 2;
 2083   
     }
 2084   
 
 2085  0
     protected boolean isGenericGetMethod(MetaMethod method) {
 2086  0
         if (method.getName().equals("get")) {
 2087  0
             Class[] parameterTypes = method.getParameterTypes();
 2088  0
             return parameterTypes.length == 1 && parameterTypes[0] == String.class;
 2089   
         }
 2090  0
         return false;
 2091   
     }
 2092   
 
 2093  0
     private void registerMethods(boolean instanceMethods) {
 2094  0
         Method[] methods = theClass.getMethods();
 2095  0
         for (int i = 0; i < methods.length; i++) {
 2096  0
             Method method = methods[i];
 2097  0
             if (MethodHelper.isStatic(method)) {
 2098  0
                 Class[] paramTypes = method.getParameterTypes();
 2099  0
                 if (paramTypes.length > 0) {
 2100  0
                     Class owner = paramTypes[0];
 2101  0
                     if (instanceMethods) {
 2102  0
                         registry.lookup(owner).addNewInstanceMethod(method);
 2103   
                     } else {
 2104  0
                         registry.lookup(owner).addNewStaticMethod(method);
 2105   
                     }
 2106   
                 }
 2107   
             }
 2108   
         }
 2109   
     }
 2110   
 
 2111  0
     protected void registerStaticMethods() {
 2112  0
         registerMethods(false);
 2113   
     }
 2114   
 
 2115  0
     protected void registerInstanceMethods() {
 2116  0
         registerMethods(true);
 2117   
     }
 2118   
 
 2119  0
     protected String capitalize(String property) {
 2120  0
         return property.substring(0, 1).toUpperCase() + property.substring(1, property.length());
 2121   
     }
 2122   
 
 2123   
     /**
 2124   
      * Call this method when any mutation method is called, such as adding a new
 2125   
      * method to this MetaClass so that any caching or bytecode generation can be
 2126   
      * regenerated.
 2127   
      */
 2128  0
     protected synchronized void onMethodChange() {
 2129  0
         reflector = null;
 2130   
     }
 2131   
     
 2132  0
     protected synchronized void checkInitialised() {
 2133  0
         if (!initialised) {
 2134  0
             initialised = true;
 2135  0
             addInheritedMethods(theClass);
 2136   
         }
 2137  0
         if (reflector == null) {
 2138  0
             generateReflector();
 2139   
         }
 2140   
     }
 2141   
 
 2142  0
     protected MetaMethod createMetaMethod(final Method method) {
 2143  0
         if (registry.useAccessible()) {
 2144  0
             AccessController.doPrivileged(new PrivilegedAction() {
 2145  0
                 public Object run() {
 2146  0
                     method.setAccessible(true);
 2147  0
                     return null;
 2148   
                 }
 2149   
             });
 2150   
         }
 2151  0
         if (useReflection) {
 2152   
             //log.warning("Creating reflection based dispatcher for: " + method);
 2153  0
             return new ReflectionMetaMethod(method);
 2154   
         }
 2155  0
         MetaMethod answer = new MetaMethod(method);
 2156  0
         if (isValidReflectorMethod(answer)) {
 2157  0
             allMethods.add(answer);
 2158  0
             answer.setMethodIndex(allMethods.size());
 2159   
         }
 2160   
         else {
 2161   
             //log.warning("Creating reflection based dispatcher for: " + method);
 2162  0
             answer = new ReflectionMetaMethod(method);
 2163   
         }
 2164  0
         return answer;
 2165   
     }
 2166   
 
 2167  0
     protected boolean isValidReflectorMethod(MetaMethod method) {
 2168   
         // We cannot use a reflector if the method is private, protected, or package accessible only.
 2169  0
         if (!method.isPublic()) {
 2170  0
             return false;
 2171   
         }
 2172  0
         Class declaringClass = method.getDeclaringClass();
 2173  0
         if (!Modifier.isPublic(declaringClass.getModifiers())) {
 2174   
             // lets see if this method is implemented on an interface
 2175  0
             List list = getInterfaceMethods();
 2176  0
             for (Iterator iter = list.iterator(); iter.hasNext();) {
 2177  0
                 MetaMethod aMethod = (MetaMethod) iter.next();
 2178  0
                 if (method.isSame(aMethod)) {
 2179  0
                     method.setInterfaceClass(aMethod.getDeclaringClass());
 2180  0
                     return true;
 2181   
                 }
 2182   
             }
 2183   
             /** todo */
 2184   
             //log.warning("Cannot invoke method on protected/private class which isn't visible on an interface so must use reflection instead: " + method);
 2185  0
             return false;
 2186   
         }
 2187  0
         return true;
 2188   
     }
 2189   
 
 2190  0
     protected void generateReflector() {
 2191  0
         reflector = loadReflector(allMethods);
 2192  0
         if (reflector == null) {
 2193  0
             throw new RuntimeException("Should have a reflector!");
 2194   
         }
 2195   
         // lets set the reflector on all the methods
 2196  0
         for (Iterator iter = allMethods.iterator(); iter.hasNext();) {
 2197  0
             MetaMethod metaMethod = (MetaMethod) iter.next();
 2198   
             //System.out.println("Setting reflector for method: " + metaMethod + " with index: " + metaMethod.getMethodIndex());
 2199  0
             metaMethod.setReflector(reflector);
 2200   
         }
 2201   
     }
 2202   
 
 2203  0
     protected Reflector loadReflector(List methods) {
 2204  0
         ReflectorGenerator generator = new ReflectorGenerator(methods);
 2205  0
         String className = theClass.getName();
 2206  0
         String packagePrefix = "gjdk.";
 2207   
         /*
 2208   
         if (className.startsWith("java.")) {
 2209   
             packagePrefix = "gjdk.";
 2210   
         }
 2211   
         */
 2212  0
         String name = packagePrefix + className + "_GroovyReflector";
 2213  0
         if (theClass.isArray()) {
 2214  0
             String componentName = theClass.getComponentType().getName();
 2215   
             /*
 2216   
             if (componentName.startsWith("java.")) {
 2217   
                 packagePrefix = "gjdk.";
 2218   
             }
 2219   
             */
 2220  0
             name = packagePrefix + componentName + "_GroovyReflectorArray";
 2221   
         }
 2222   
         // lets see if its already loaded
 2223  0
         try {
 2224  0
             Class type = loadReflectorClass(name);
 2225  0
             return (Reflector) type.newInstance();
 2226   
         }
 2227   
         catch (AccessControlException ace) {
 2228   
             //Don't ignore this exception type
 2229  0
             throw ace;
 2230   
         } 
 2231   
         catch (Exception e) {
 2232   
             // lets ignore, lets generate it && load it
 2233   
         }
 2234   
 
 2235  0
         ClassWriter cw = new ClassWriter(true);
 2236  0
         generator.generate(cw, name);
 2237   
 
 2238  0
         byte[] bytecode = cw.toByteArray();
 2239   
 
 2240  0
         try {
 2241  0
             Class type = loadReflectorClass(name, bytecode);
 2242  0
             return (Reflector) type.newInstance();
 2243   
         }
 2244   
         catch (Exception e) {
 2245  0
             throw new GroovyRuntimeException("Could not load the reflector for class: " + name + ". Reason: " + e, e);
 2246   
         }
 2247   
     }
 2248   
 
 2249  0
     protected Class loadReflectorClass(final String name, final byte[] bytecode) throws ClassNotFoundException {
 2250  0
         ClassLoader loader = theClass.getClassLoader();
 2251  0
         if (loader instanceof GroovyClassLoader) {
 2252  0
             final GroovyClassLoader gloader = (GroovyClassLoader) loader;
 2253  0
             return (Class) AccessController.doPrivileged(new PrivilegedAction() {
 2254  0
                 public Object run() {
 2255  0
                     return gloader.defineClass(name, bytecode, getClass().getProtectionDomain());
 2256   
                 }
 2257   
             });
 2258   
         }
 2259  0
         return registry.loadClass(name, bytecode);
 2260   
     }
 2261   
 
 2262  0
     protected Class loadReflectorClass(String name) throws ClassNotFoundException {
 2263  0
         ClassLoader loader = theClass.getClassLoader();
 2264  0
         if (loader instanceof GroovyClassLoader) {
 2265  0
             GroovyClassLoader gloader = (GroovyClassLoader) loader;
 2266  0
             return gloader.loadClass(name);
 2267   
         }
 2268  0
         return registry.loadClass(name);
 2269   
     }
 2270   
 
 2271  0
     public List getMethods() {
 2272  0
         return allMethods;
 2273   
     }
 2274   
 
 2275  0
     public List getMetaMethods() {
 2276  0
         return (List) ((ArrayList)newGroovyMethodsList).clone();
 2277   
     }
 2278   
 
 2279  0
     protected synchronized List getInterfaceMethods() {
 2280  0
         if (interfaceMethods == null) {
 2281  0
             interfaceMethods = new ArrayList();
 2282  0
             Class type = theClass;
 2283  0
             while (type != null) {
 2284  0
                 Class[] interfaces = type.getInterfaces();
 2285  0
                 for (int i = 0; i < interfaces.length; i++) {
 2286  0
                     Class iface = interfaces[i];
 2287  0
                     Method[] methods = iface.getMethods();
 2288  0
                     addInterfaceMethods(interfaceMethods, methods);
 2289   
                 }
 2290  0
                 type = type.getSuperclass();
 2291   
             }
 2292   
         }
 2293  0
         return interfaceMethods;
 2294   
     }
 2295   
 
 2296  0
     private void addInterfaceMethods(List list, Method[] methods) {
 2297  0
         for (int i = 0; i < methods.length; i++) {
 2298  0
             list.add(createMetaMethod(methods[i]));
 2299   
         }
 2300   
     }
 2301   
 
 2302   
     /**
 2303   
      * param instance array to the type array
 2304   
      * @param args
 2305   
      * @return
 2306   
      */
 2307  0
     Class[] convertToTypeArray(Object[] args) {
 2308  0
         if (args == null)
 2309  0
             return null;
 2310  0
         int s = args.length;
 2311  0
         Class[] ans = new Class[s];
 2312  0
         for (int i = 0; i < s; i++) {
 2313  0
             Object o = args[i];
 2314  0
             if (o != null) {
 2315  0
                 ans[i] = o.getClass();
 2316   
             } else {
 2317  0
                 ans[i] = null;
 2318   
             }
 2319   
         }
 2320  0
         return ans;
 2321   
     }
 2322   
 }
 2323