metaclassimpl.java

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

JAVA
1,511
字号
           // we may have already found one for this name
           if (isGetter && mbp.getGetter()==null) {
               mbp.setGetter(propertyMethod);
           } else if (!isGetter && mbp.getSetter()==null) {
               mbp.setSetter(propertyMethod);
           }
           mbp.setField(mfp);
           mp = mbp;
       }
       propertyIndex.put(propName, mp);
   }

   private void applyPropertyDescriptors(PropertyDescriptor[] propertyDescriptors) {
       Map propertyMap = (Map) classPropertyIndex.get(theClass);
       // now iterate over the map of property descriptors and generate
       // MetaBeanProperty objects
       for(int i=0; i<propertyDescriptors.length; i++) {
           PropertyDescriptor pd = propertyDescriptors[i];
           
           // skip if the property type is unknown (this seems to be the case if the
           // property descriptor is based on a setX() method that has two parameters,
           // which is not a valid property)
           if(pd.getPropertyType() == null)
               continue;
           
           // get the getter method
           Method method = pd.getReadMethod();
           MetaMethod getter;
           if(method != null)
               getter = findMethod(method);
           else
               getter = null;
           
           // get the setter method
           MetaMethod setter;
           method = pd.getWriteMethod();
           if(method != null)
               setter = findMethod(method);
           else
               setter = null;
           
           // now create the MetaProperty object
           MetaBeanProperty mp = new MetaBeanProperty(pd.getName(), pd.getPropertyType(), getter, setter);
           
           //keep field
           MetaFieldProperty field = null;
           MetaProperty old = (MetaProperty) propertyMap.get(pd.getName());
           if (old!=null) {
               if (old instanceof MetaBeanProperty) {
                   field = ((MetaBeanProperty) old).getField();
               } else {
                   field = (MetaFieldProperty) old;
               }
               mp.setField(field);
           }
           
           // put it in the list
           // this will overwrite a possible field property
           propertyMap.put(pd.getName(), mp);
       }       
   }
   
   /**
    * Sets the property value on an object
    */
   public void setProperty(Class sender,Object object, String name, Object newValue, boolean useSuper, boolean fromInsideClass) {
       checkInitalised();
       
       //----------------------------------------------------------------------
       // handling of static
       //----------------------------------------------------------------------
       boolean isStatic = theClass != Class.class && object instanceof Class;
       if (isStatic && object != theClass) {
           MetaClass mc = registry.getMetaClass((Class) object);
           mc.getProperty(sender,object,name,useSuper,fromInsideClass);
           return;
       }
       
       //----------------------------------------------------------------------
       // Unwrap wrapped values fo now - the new MOP will handle them properly
       //----------------------------------------------------------------------
       if (newValue instanceof Wrapper) newValue = ((Wrapper)newValue).unwrap();
       
       
    
       MetaMethod method = null;
       Object[] arguments = null;

       //----------------------------------------------------------------------
       // setter
       //----------------------------------------------------------------------
       MetaProperty mp = getMetaProperty(sender,name,useSuper, isStatic);
       MetaProperty field = null;
       if (mp != null) {
           if (mp instanceof MetaBeanProperty) {
               MetaBeanProperty mbp = (MetaBeanProperty) mp;
               method = mbp.getSetter();
               if (method!=null) arguments = new Object[] { newValue };
               field = mbp.getField();
           } else {
               field = mp;
           }
       }
       
       // check for a category method named like a setter 
       if (!useSuper && !isStatic && GroovyCategorySupport.hasCategoryInAnyThread()) {
           String getterName = "set"+MetaClassHelper.capitalize(name);
           method = getCategoryMethodSetter(sender,getterName,false);
           if (method!=null) arguments = new Object[] { newValue };
       }

       //----------------------------------------------------------------------
       // listener method
       //----------------------------------------------------------------------
       boolean ambigousListener = false;
       boolean usesProxy = false;
       if (method==null) {
           method = (MetaMethod) listeners.get(name);
           ambigousListener = method == AMBIGOUS_LISTENER_METHOD;
           if ( method != null && 
                !ambigousListener &&
                newValue instanceof Closure) 
           {
               // lets create a dynamic proxy
               Object proxy =
                   MetaClassHelper.createListenerProxy(method.getParameterTypes()[0], name, (Closure) newValue);
               arguments = new Object[] { proxy };
               newValue = proxy;
               usesProxy = true;
           } else {
               method = null;
           }
       }
       
       //----------------------------------------------------------------------
       // field
       //----------------------------------------------------------------------
       if (method==null && field!=null) {
           field.setProperty(object,newValue);
           return;
       }       

       //----------------------------------------------------------------------
       // generic set method
       //----------------------------------------------------------------------       
       // check for a generic get method provided through a category
       if (method==null && !useSuper && !isStatic && GroovyCategorySupport.hasCategoryInAnyThread()) {
           method = getCategoryMethodSetter(sender,"set",true);
           if (method!=null) arguments = new Object[]{name,newValue};
       }

       // the generic method is valid, if available (!=null), if static or
       // if it is not static and we do no static access
       if (method==null && genericSetMethod != null && !(!genericSetMethod.isStatic() && isStatic)) {
           arguments = new Object[]{ name, newValue };
           method = genericSetMethod;
       } 
       
       //----------------------------------------------------------------------
       // executing the getter method 
       //----------------------------------------------------------------------
       if (method!=null) {
           if (arguments.length==1) {
               newValue = DefaultTypeTransformation.castToType(
                       newValue,
                       method.getParameterTypes()[0]);
               arguments[0] = newValue;
           } else {
               newValue = DefaultTypeTransformation.castToType(
                       newValue,
                       method.getParameterTypes()[1]);
               arguments[1] = newValue;
           }
           MetaClassHelper.doMethodInvoke(object,method,arguments);
           return;
       }
           
       //----------------------------------------------------------------------
       // error due to missing method/field
       //----------------------------------------------------------------------
       if (ambigousListener){
           throw new GroovyRuntimeException("There are multiple listeners for the property "+name+". Please do not use the bean short form to access this listener.");
       } 
       throw new MissingPropertyException(name, theClass);   
   }
   
   private MetaProperty getMetaProperty(Class clazz, String name, boolean useSuper, boolean useStatic) {
       Map propertyMap;
       if (useStatic) {
           propertyMap = staticPropertyIndex;
       } else if (useSuper){
           propertyMap = (Map) classPropertyIndexForSuper.get(clazz);
       } else {
           propertyMap = (Map) classPropertyIndex.get(clazz);
       }
       if (propertyMap==null) {
           if (clazz!=theClass) {
               return getMetaProperty(theClass,name,useSuper, useStatic);
           } else {
               return null;
           }           
       }
       return (MetaProperty) propertyMap.get(name);
   }


   /**
    * Looks up the given attribute (field) on the given object
    */
   public Object getAttribute(Class sender, Object object, String attribute, boolean useSuper, boolean fromInsideClass) {
       checkInitalised();
       
       boolean isStatic = theClass != Class.class && object instanceof Class;
       if (isStatic && object != theClass) {
           MetaClass mc = registry.getMetaClass((Class) object);
           return mc.getAttribute(sender,object,attribute,useSuper);
       }
    
       MetaProperty mp = getMetaProperty(sender,attribute,useSuper, isStatic);
       
       if (mp != null) {
           if (mp instanceof MetaBeanProperty) {
               MetaBeanProperty mbp = (MetaBeanProperty) mp;
               mp = mbp.getField();
           }
           try {
               // delegate the get operation to the metaproperty
               if (mp != null) return mp.getProperty(object);
           } catch(Exception e) {
               throw new GroovyRuntimeException("Cannot read field: " + attribute,e);
           }
       }
       
       throw new MissingFieldException(attribute, theClass);
   }

   /**
    * Sets the given attribute (field) on the given object
    */
   public void setAttribute(Class sender, Object object, String attribute, Object newValue, boolean useSuper, boolean fromInsideClass) {
       checkInitalised();
       
       boolean isStatic = theClass != Class.class && object instanceof Class;
       if (isStatic && object != theClass) {
           MetaClass mc = registry.getMetaClass((Class) object);
           mc.setAttribute(sender,object,attribute,newValue,useSuper,fromInsideClass);
           return;
       }
    
       MetaProperty mp = getMetaProperty(sender,attribute,useSuper, isStatic);
       
       if (mp != null) {
           if (mp instanceof MetaBeanProperty) {
               MetaBeanProperty mbp = (MetaBeanProperty) mp;
               mp = mbp.getField();
           }
           if (mp != null) {
               mp.setProperty(object,newValue);
               return;
           }
       }
       
       throw new MissingFieldException(attribute, theClass);
   }

   public ClassNode getClassNode() {
       if (classNode == null && GroovyObject.class.isAssignableFrom(theClass)) {
           // lets try load it from the classpath
           String className = theClass.getName();
           String groovyFile = className;
           int idx = groovyFile.indexOf('$');
           if (idx > 0) {
               groovyFile = groovyFile.substring(0, idx);
           }
           groovyFile = groovyFile.replace('.', '/') + ".groovy";

           //System.out.println("Attempting to load: " + groovyFile);
           URL url = theClass.getClassLoader().getResource(groovyFile);
           if (url == null) {
               url = Thread.currentThread().getContextClassLoader().getResource(groovyFile);
           }
           if (url != null) {
               try {

                   /**
                    * todo there is no CompileUnit in scope so class name
                    * checking won't work but that mostly affects the bytecode
                    * generation rather than viewing the AST
                    */
                   CompilationUnit.ClassgenCallback search = new CompilationUnit.ClassgenCallback() {
                       public void call( ClassVisitor writer, ClassNode node ) {
                           if( node.getName().equals(theClass.getName()) ) {
                               MetaClassImpl.this.classNode = node;
                           }
                       }
                   };

                   final ClassLoader parent = theClass.getClassLoader();
                   GroovyClassLoader gcl = (GroovyClassLoader) AccessContr

⌨️ 快捷键说明

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