View Javadoc

    1   /*
    2    * Copyright 2005 John G. Wilson
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *     http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   *
    16   */
    17
    18  package groovy.lang;
    19
    20  import java.lang.reflect.Method;
    21  import java.util.List;
    22  import java.util.logging.Logger;
    23
    24  import org.codehaus.groovy.ast.ClassNode;
    25  import org.codehaus.groovy.runtime.MetaClassHelper;
    26
    27  /***
    28   * Base class for meta class implementations.
    29   * The meta class is used to invoke methods or to get
    30   * fields/properties. For proper initialization of this class
    31   * it is not enough to only call the constructor, the
    32   * initialize() must be called too. The invoke methods should
    33   * check that initialize() was called. Adding methods is
    34   * valid unless initilise method was called. Therefore
    35   * addNewStaticMethod and addNewInstanceMethod should check that
    36   * that initilise awas not called before.
    37   *
    38   *
    39   * @author John Wilson
    40   *
    41   */
    42
    43  public abstract class MetaClass {
    44      protected static final Logger log = Logger.getLogger(MetaClass.class.getName());
    45      protected static boolean useReflection = false;
    46      public static final Object NO_METHOD_FOUND = new Object();
    47      protected final Class theClass;
    48      private boolean isGroovyObject;
    49
    50      public static boolean isUseReflection() {
    51          return MetaClass.useReflection;
    52      }
    53
    54      /***
    55       * Allows reflection to be enabled in situations where bytecode generation
    56       * of method invocations causes issues.
    57       *
    58       * @param useReflection
    59       */
    60      public static void setUseReflection(boolean useReflection) {
    61          MetaClass.useReflection = useReflection;
    62      }
    63
    64      protected MetaClass(final Class theClass) {
    65          this.theClass = theClass;
    66          isGroovyObject = GroovyObject.class.isAssignableFrom(theClass);
    67      }
    68
    69      public boolean isGroovyObject(){
    70          return isGroovyObject;
    71      }
    72
    73      public Object invokeMissingMethod(Object instance, String methodName, Object[] arguments) {
    74          GroovyObject pogo = (GroovyObject) instance;
    75          return pogo.invokeMethod(methodName,arguments);
    76      }
    77
    78      public Object invokeMethod(Object object, String methodName, Object arguments) {
    79          if (arguments == null) {
    80              return invokeMethod(object, methodName, MetaClassHelper.EMPTY_ARRAY);
    81          }
    82          if (arguments instanceof Tuple) {
    83              Tuple tuple = (Tuple) arguments;
    84              return invokeMethod(object, methodName, tuple.toArray());
    85          }
    86          if (arguments instanceof Object[]) {
    87              return invokeMethod(object, methodName, (Object[])arguments);
    88          }
    89          else {
    90              return invokeMethod(object, methodName, new Object[]{arguments});
    91          }
    92      }
    93
    94      public Object invokeMethod(Class sender, Object receiver, String methodName, Object[] arguments, boolean isCallToSuper, boolean fromInsideClass){
    95          return invokeMethod(receiver,methodName,arguments);
    96      }
    97
    98      public Object getProperty(Class sender, Object receiver, String messageName, boolean useSuper, boolean fromInsideClass) {
    99          return getProperty(receiver,messageName);
    100     }
    101
    102     public void setProperty(Class sender, Object receiver, String messageName, Object messageValue, boolean useSuper, boolean fromInsideClass) {
    103         setProperty(receiver,messageName,messageValue);
    104     }
    105
    106     public Object getAttribute(Class sender, Object receiver, String messageName, boolean useSuper) {
    107         return getAttribute(receiver,messageName);
    108     }
    109
    110     public void setAttribute(Class sender, Object receiver, String messageName, Object messageValue, boolean useSuper, boolean fromInsideClass) {
    111         setAttribute(receiver,messageName,messageValue);
    112     }
    113
    114     public abstract Object invokeConstructor(Object[] arguments);
    115     public abstract Object invokeMethod(Object object, String methodName, Object[] arguments);
    116     public abstract Object invokeStaticMethod(Object object, String methodName, Object[] arguments);
    117     public abstract Object getProperty(Object object, String property);
    118     public abstract void setProperty(Object object, String property, Object newValue);
    119     public abstract Object getAttribute(Object object, String attribute);
    120     public abstract void setAttribute(Object object, String attribute, Object newValue);
    121     /***
    122      * adds a new instance method to this meta class. Instance
    123      * methods are able to overwrite the original methods of the
    124      * class. Calling this method should not be done after
    125      * initlise was called.
    126      * @param method the method to be added
    127      */
    128     public abstract void addNewInstanceMethod(Method method);
    129     /***
    130      * adds a new static method to this meta class. This is only
    131      * possible as long as initilise was not called.
    132      * @param method the method to be added
    133      */
    134     public abstract void addNewStaticMethod(Method method);
    135     /***
    136      * complete the initlialisation process. After this method
    137      * is called no methods should be added to the meta class.
    138      * Invocation of methods or access to fields/proeprties is
    139      * forbidden unless this method is called. This method
    140      * should contain any initialisation code, taking a longer
    141      * time to complete. An example is the creation of the
    142      * Reflector. It is suggested to synchronize this
    143      * method.
    144      */
    145     public abstract void initialize();
    146
    147     public abstract List getProperties();
    148     public abstract ClassNode getClassNode();
    149     public abstract List getMetaMethods();
    150
    151     public abstract List getMethods();
    152
    153     /***
    154      * Warning, this method will be removed
    155      * @deprecated use invokeConstructor instead
    156      */
    157     public Object invokeConstructorAt(Class at, Object[] arguments) {
    158         return invokeConstructor(arguments);
    159     }
    160
    161     /***
    162      * Selects a method by name and argument classes. This method
    163      * does not search for an exact match, it searches for a compatible
    164      * method. For this the method selection mechanism is used as provided
    165      * bye the implementation of this MetaClass. pickMethod may or may
    166      * not used during the method selection process when invoking a method
    167      * thereis no warranty for that.
    168      *
    169      * @returns a matching MetaMethod or null
    170      * @throws GroovyRuntimeException if there is more than one matching method
    171      */
    172     public abstract MetaMethod pickMethod(String methodName, Class[] arguments);
    173
    174     /***
    175      * Warning, this method will be removed
    176      * @deprecated usw pickMethod instead
    177      */
    178     protected MetaMethod retrieveMethod(String methodName, Class[] arguments) {
    179         return pickMethod(methodName,arguments);
    180     }
    181
    182 }