metaclassimpl.java

来自「Groovy动态语言 运行在JVM中的动态语言 可以方便的处理业务逻辑变化大的业」· Java 代码 · 共 1,511 行 · 第 1/5 页

JAVA
1,511
字号
               continue;
           }
           copyNonPrivateMethods(currentIndex,methodIndex);
       }
   }
   
   private static void makeInterfaceSet(Class c, Set s) {
       if (c==null) return;
       Class[] interfaces = c.getInterfaces();
       for (int i = 0; i < interfaces.length; i++) {
           if (!s.contains(interfaces[i])) {
               s.add(interfaces[i]);
               makeInterfaceSet(interfaces[i],s);
           }
       }
       makeInterfaceSet(c.getSuperclass(),s);
   }
   
   private void copyNonPrivateMethods(Map from, Map to) {
       for (Iterator iterator = from.entrySet().iterator(); iterator.hasNext();) {
           Map.Entry element = (Map.Entry) iterator.next();
           List oldList = (List) element.getValue();
           List newList = (List) to.get(element.getKey());
           if (newList==null) {
               to.put(element.getKey(),new ArrayList(oldList));
           } else {
               addNonPrivateMethods(newList,oldList);
           }
       }
   }
   
   private void connectMultimethods(List superClasses){
       superClasses = DefaultGroovyMethods.reverse(superClasses);
       Map last = null;
       for (Iterator iter = superClasses.iterator(); iter.hasNext();) {
           Class c = (Class) iter.next();
           Map methodIndex = (Map) classMethodIndex.get(c);
           if (methodIndex==last) continue;
           if (last!=null) copyNonPrivateMethods(last,methodIndex);
           last = methodIndex;
       }
   }
   
   private void inheritMethods(Collection superClasses, Map classMethodIndex){
       Map last = null;
       for (Iterator iter = superClasses.iterator(); iter.hasNext();) {
           Class c = (Class) iter.next();
           Map methodIndex = (Map) classMethodIndex.get(c);
           if (last!=null) {
               if (methodIndex.size()==0) {
                   classMethodIndex.put(c,last);
                   continue;
               }
               copyNonPrivateMethods(last,methodIndex);
           }
           last = methodIndex;
       }
   }

   private void addNonPrivateMethods(List newList, List oldList) {
       for (Iterator iter = oldList.iterator(); iter.hasNext();) {
           MetaMethod element = (MetaMethod) iter.next();
           if (element.isPrivate()) continue;
           addMethodToList(newList,element);
       }
   }

/**
    * @return all the normal instance methods avaiable on this class for the
    *         given name
    */
   private List getMethods(Class sender, String name, boolean isCallToSuper) {
       Map methodIndex;
       if (isCallToSuper) {
           methodIndex = (Map) classMethodIndexForSuper.get(sender);
       } else {
           methodIndex = (Map) classMethodIndex.get(sender);
       }   
       List answer;
       if (methodIndex!=null) {
           answer = (List) methodIndex.get(name);
           if (answer == null) answer = Collections.EMPTY_LIST;
       } else {
           answer = Collections.EMPTY_LIST;
       }
       
       if (!isCallToSuper && GroovyCategorySupport.hasCategoryInAnyThread()) {
           List used = GroovyCategorySupport.getCategoryMethods(sender, name);
           if (used != null) {
               answer = new ArrayList(answer);
               for (Iterator iter = used.iterator(); iter.hasNext();) {
                   MetaMethod element = (MetaMethod) iter.next();
                   removeMatchingMethod(answer,element);
               }
               answer.addAll(used);
           }
       }
       return answer;
   }

   /**
    * @return all the normal static methods avaiable on this class for the
    *         given name
    */
   private List getStaticMethods(Class sender, String name) {
       Map methodIndex = (Map) classStaticMethodIndex.get(sender);
       if (methodIndex == null) return Collections.EMPTY_LIST;
       List answer = (List) methodIndex.get(name);
       if (answer == null) return Collections.EMPTY_LIST;
       return answer;
   }

   public void addNewInstanceMethod(Method method) {
       NewInstanceMetaMethod newMethod = new NewInstanceMetaMethod(createMetaMethod(method));
       if (! newGroovyMethodsList.contains(newMethod)){
           newGroovyMethodsList.add(newMethod);
           addMetaMethod(newMethod);
       }
   }

   public void addNewStaticMethod(Method method) {
       NewStaticMetaMethod newMethod = new NewStaticMetaMethod(createMetaMethod(method));
       if (! newGroovyMethodsList.contains(newMethod)){
           newGroovyMethodsList.add(newMethod);
           addMetaMethod(newMethod);
       }
   }

   private void unwrap(Object[] arguments) {
       //
       // Temp code to ignore wrapped parameters
       // The New MOP will deal with these properly
       //
       for (int i = 0; i != arguments.length; i++) {
        if (arguments[i] instanceof Wrapper) {
          arguments[i] = ((Wrapper)arguments[i]).unwrap();
        }
       }       
   }
   
   
   /**
    * Invokes the given method on the object.
    * @deprecated
    */
   public Object invokeMethod(Object object, String methodName, Object[] originalArguments) {
       return invokeMethod(theClass,object,methodName,originalArguments,false,false);
   }
   
   
   /**
    * Invokes the given method on the object.
    *
    */
   public Object invokeMethod(Class sender, Object object, String methodName, Object[] originalArguments, boolean isCallToSuper, boolean fromInsideClass) {
       checkInitalised();
       if (object == null) {
           throw new NullPointerException("Cannot invoke method: " + methodName + " on null object");
       }              
       if (log.isLoggable(Level.FINER)){
           MetaClassHelper.logMethodCall(object, methodName, originalArguments);
       }
       Object[] arguments = originalArguments;
       if (arguments==null) arguments = EMPTY_ARGUMENTS;
       Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
       unwrap(arguments);
       
       MetaMethod method = getMethodWithCaching(sender, methodName, argClasses, isCallToSuper);
       
       if (method==null && arguments.length==1 && arguments[0] instanceof List) {
           Object[] newArguments = ((List) arguments[0]).toArray();
           Class[] newArgClasses = MetaClassHelper.convertToTypeArray(newArguments);
           method = getMethodWithCaching(sender, methodName, newArgClasses, isCallToSuper);
           if (method!=null) {
               MethodKey methodKey = new DefaultMethodKey(sender, methodName, argClasses, isCallToSuper);
               method = new TransformMetaMethod(method) {
                   public Object invoke(Object object, Object[] arguments) {
                       Object firstArgument = arguments[0];
                       List list = (List) firstArgument;
                       arguments = list.toArray();
                       return super.invoke(object, arguments);
                   }
               };
               cacheInstanceMethod(methodKey, method);
               return invokeMethod(sender,object,methodName, originalArguments, isCallToSuper, fromInsideClass);
           }
       }

       boolean isClosure = object instanceof Closure;
       if (isClosure) {
           Closure closure = (Closure) object;
           Object delegate = closure.getDelegate();
           Object owner = closure.getOwner();
           
           
           if ("call".equals(methodName) || "doCall".equals(methodName)) {
               if (object.getClass()==MethodClosure.class) {
                   MethodClosure mc = (MethodClosure) object;
                   methodName = mc.getMethod();
                   Class ownerClass = owner.getClass();
                   if (owner instanceof Class) ownerClass = (Class) owner;
                   MetaClass ownerMetaClass = registry.getMetaClass(ownerClass);
                   return ownerMetaClass.invokeMethod(ownerClass,owner,methodName,arguments,false,false);
               } else if (object.getClass()==CurriedClosure.class) {
                   CurriedClosure cc = (CurriedClosure) object;
                   // change the arguments for an uncurried call
                   arguments = cc.getUncurriedArguments(arguments);
                   Class ownerClass = owner.getClass();
                   if (owner instanceof Class) ownerClass = (Class) owner;
                   MetaClass ownerMetaClass = registry.getMetaClass(ownerClass);
                   return ownerMetaClass.invokeMethod(owner,methodName,arguments);
               }
           } else if ("curry".equals(methodName)) {
               return closure.curry(arguments);
           }

           if (method==null && owner!=closure) {
               Class ownerClass = owner.getClass();
               if (owner instanceof Class) ownerClass = (Class) owner;
               MetaClass ownerMetaClass = registry.getMetaClass(ownerClass);
               method = ownerMetaClass.pickMethod(methodName,argClasses);
               if (method!=null) return ownerMetaClass.invokeMethod(owner,methodName,originalArguments);
           }
           if (method==null && delegate!=closure && delegate!=null) {
               Class delegateClass = delegate.getClass();
               if (delegate instanceof Class) delegateClass = (Class) delegate;
               MetaClass delegateMetaClass = registry.getMetaClass(delegateClass);
               method = delegateMetaClass.pickMethod(methodName,argClasses);
               if (method!=null) return delegateMetaClass.invokeMethod(delegate,methodName,originalArguments);
           }
           if (method==null) {
               // still no methods found, test if delegate or owner are GroovyObjects
               // and invoke the method on them if so.
               MissingMethodException last = null;
               if (owner!=closure && (owner instanceof GroovyObject)) {
                   try {
                       GroovyObject go = (GroovyObject) owner;
                       return go.invokeMethod(methodName,originalArguments);
                   } catch (MissingMethodException mme) {
                       if (last==null) last = mme;
                   }
               }
               if (delegate!=closure && (delegate instanceof GroovyObject)) {
                   try {
                       GroovyObject go = (GroovyObject) delegate;
                       return go.invokeMethod(methodName,originalArguments);
                   } catch (MissingMethodException mme) {
                       last = mme;
                   }
               }
               if (last!=null) throw last;
           }

       }

       if (method != null) {
           return MetaClassHelper.doMethodInvoke(object, method, arguments);
       } else {
           // if no method was found, try to find a closure defined as a field of the class and run it
           try {
               Object value = this.getProperty(object, methodName);
               if (value instanceof Closure) {  // This test ensures that value != this If you ever change this ensure that value != this
                   Closure closure = (Closure) value;
                   MetaClass delegateMetaClass = closure.getMetaClass();
                   return delegateMetaClass.invokeMethod(closure.getClass(),closure,"doCall",originalArguments,false,fromInsideClass);
               }
           } catch (MissingPropertyException mpe) {}

           throw new MissingMethodException(methodName, theClass, originalArguments, false);
       }
   }
   
   public MetaMethod getMethodWithCaching(Class sender, String methodName, Class[] arguments, boolean isCallToSuper) {
       // lets try use the cache to find the method
       if (GroovyCategorySupport.hasCategoryInAnyThread() && !isCallToSuper) {
           return getMethodWithoutCaching(sender, methodName, arguments, isCallToSuper);
       } else {
           MethodKey methodKey = new DefaultMethodKey(sender, methodName, arguments, isCallToSuper);
           MetaMethod method = (MetaMethod) methodCache.get(methodKey);
           if (method == null) {
               method = getMethodWithoutCaching(sender, methodName, arguments, isCallToSuper);
               cacheInstanceMethod(methodKey, method);
           }
           return method;
       }
   }
   
   protected void cacheInstanceMethod(MethodKey key, MetaMethod method) {
       if (method != null && method.isCacheable()) {
           methodCache.put(key, method);
       }
   }

   protected void cacheStaticMethod(MethodKey key, MetaMethod method) {
       if (method != null && method.isCacheable()) {
           staticMethodCache.put(key, method);
       }
   }

   
   public Constructor retrieveConstructor(Class[] arguments) {
       Constructor constructor = (Constructor) chooseMethod("<init>", constructors, arguments, false);
       if (constructor != null) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?