Save This Page
Home » Groovy-1.7.0 » org.codehaus » groovy » runtime » callsite » [javadoc | source]
    1   /*
    2    * Copyright 2003-2007 the original author or authors.
    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   package org.codehaus.groovy.runtime.callsite;
   17   
   18   import groovy.lang.MetaClass;
   19   import groovy.lang.MetaClassImpl;
   20   import groovy.lang.GroovyInterceptable;
   21   import groovy.lang.GroovyObject;
   22   import org.codehaus.groovy.runtime.InvokerHelper;
   23   import org.codehaus.groovy.reflection.ClassInfo;
   24   
   25   public final class CallSiteArray {
   26       public final CallSite[] array;
   27   
   28       public static final Object [] NOPARAM = new Object[0];
   29       public final Class owner;
   30   
   31       public CallSiteArray(Class owner, String [] names) {
   32           this.owner = owner;
   33           array = new CallSite[names.length];
   34           for (int i = 0; i < array.length; i++) {
   35               array[i] = new AbstractCallSite(this, i, names[i]);
   36           }
   37       }
   38   
   39       public static Object defaultCall(CallSite callSite, Object receiver, Object[] args) throws Throwable {
   40           return createCallSite(callSite, receiver, args).call(receiver, args);
   41       }
   42   
   43       public static Object defaultCallCurrent(CallSite callSite, GroovyObject receiver, Object[] args) throws Throwable {
   44           return createCallCurrentSite(callSite, receiver, args, callSite.getArray().owner).callCurrent(receiver, args);
   45       }
   46   
   47       public static Object defaultCallStatic(CallSite callSite, Class receiver, Object[] args) throws Throwable {
   48           return createCallStaticSite(callSite, receiver, args).callStatic(receiver,args);
   49       }
   50   
   51       public static Object defaultCallConstructor(CallSite callSite, Object receiver, Object[] args) throws Throwable {
   52           return createCallConstructorSite(callSite, (Class) receiver, args).callConstructor(receiver, args);
   53       }
   54   
   55       private static CallSite createCallStaticSite(CallSite callSite, Class receiver, Object[] args) {
   56           CallSite site;
   57           MetaClass metaClass = InvokerHelper.getMetaClass(receiver);
   58           if (metaClass instanceof MetaClassImpl) {
   59               site = ((MetaClassImpl)metaClass).createStaticSite(callSite, args);
   60           }
   61           else
   62             site = new StaticMetaClassSite(callSite, metaClass);
   63   
   64           replaceCallSite(callSite, site);
   65           return site;
   66       }
   67   
   68       private static CallSite createCallConstructorSite(CallSite callSite, Class receiver, Object[] args) {
   69          MetaClass metaClass = InvokerHelper.getMetaClass(receiver);
   70   
   71          CallSite site;
   72          if (metaClass instanceof MetaClassImpl) {
   73              site = ((MetaClassImpl)metaClass).createConstructorSite(callSite, args);
   74          }
   75          else
   76            site = new MetaClassConstructorSite(callSite, metaClass);
   77   
   78           replaceCallSite(callSite, site);
   79           return site;
   80       }
   81   
   82       private static CallSite createCallCurrentSite(CallSite callSite, GroovyObject receiver, Object[] args, Class sender) {
   83           CallSite site;
   84           if (receiver instanceof GroovyInterceptable)
   85             site = new PogoInterceptableSite(callSite);
   86           else {
   87               MetaClass metaClass = receiver.getMetaClass();
   88               if (receiver.getClass() != metaClass.getTheClass() && !metaClass.getTheClass().isInterface()) {
   89                   site = new PogoInterceptableSite(callSite);
   90               }
   91               else
   92                   if (metaClass instanceof MetaClassImpl) {
   93                       site = ((MetaClassImpl)metaClass).createPogoCallCurrentSite(callSite, sender, args);
   94                   }
   95                   else
   96                     site = new PogoMetaClassSite(callSite, metaClass);
   97           }
   98   
   99           replaceCallSite(callSite, site);
  100           return site;
  101       }
  102   
  103       // for MetaClassImpl we try to pick meta method,
  104       // otherwise or if method doesn't exist we make call via POJO meta class
  105       private static CallSite createPojoSite(CallSite callSite, Object receiver, Object[] args) {
  106           final Class klazz = receiver.getClass();
  107           MetaClass metaClass = InvokerHelper.getMetaClass(receiver);
  108           if (callSite.getUsage().get() == 0 && metaClass instanceof MetaClassImpl) {
  109               final MetaClassImpl mci = (MetaClassImpl) metaClass;
  110               final ClassInfo info = mci.getTheCachedClass().classInfo;
  111               if (info.hasPerInstanceMetaClasses()) {
  112                   return new PerInstancePojoMetaClassSite(callSite, info);
  113               } else {
  114                   return mci.createPojoCallSite(callSite, receiver, args);
  115               }
  116           }
  117   
  118           ClassInfo info = ClassInfo.getClassInfo(klazz);
  119           if (info.hasPerInstanceMetaClasses())
  120             return new PerInstancePojoMetaClassSite(callSite, info);
  121           else
  122             return new PojoMetaClassSite(callSite, metaClass);
  123       }
  124   
  125       private static CallSite createPogoSite(CallSite callSite, Object receiver, Object[] args) {
  126           if (receiver instanceof GroovyInterceptable)
  127             return new PogoInterceptableSite(callSite);
  128   
  129           MetaClass metaClass = ((GroovyObject)receiver).getMetaClass();
  130   
  131           if (metaClass instanceof MetaClassImpl) {
  132               return ((MetaClassImpl)metaClass).createPogoCallSite(callSite, args);
  133           }
  134   
  135           return new PogoMetaClassSite(callSite, metaClass);
  136       }
  137   
  138       private static CallSite createCallSite(CallSite callSite, Object receiver, Object[] args) {
  139           CallSite site;
  140           if (receiver == null)
  141             return new NullCallSite(callSite);
  142   
  143           if (receiver instanceof Class)
  144             site = createCallStaticSite(callSite, (Class) receiver, args);
  145           else if (receiver instanceof GroovyObject) {
  146               site = createPogoSite(callSite, receiver, args);
  147           } else {
  148               site = createPojoSite(callSite, receiver, args);
  149           }
  150   
  151           replaceCallSite(callSite, site);
  152           return site;
  153       }
  154   
  155       private static void replaceCallSite(CallSite oldSite, CallSite newSite) {
  156           oldSite.getArray().array [oldSite.getIndex()] = newSite;
  157       }
  158   }

Save This Page
Home » Groovy-1.7.0 » org.codehaus » groovy » runtime » callsite » [javadoc | source]