PropertyUtils.copyProperties源碼

public PropertyDescriptor getPropertyDescriptor(Object bean,
                                                           String name)
            throws IllegalAccessException, InvocationTargetException,
            NoSuchMethodException {

        if (bean == null) {
            throw new IllegalArgumentException("No bean specified");
        }
        if (name == null) {
            throw new IllegalArgumentException("No name specified for bean class '" +
                    bean.getClass() + "'");
        }

        // Resolve nested references
        while (resolver.hasNested(name)) {
            String next = resolver.next(name);
            Object nestedBean = getProperty(bean, next);
            if (nestedBean == null) {
                throw new NestedNullException
                        ("Null property value for '" + next +
                        "' on bean class '" + bean.getClass() + "'");
            }
            bean = nestedBean;
            name = resolver.remove(name);
        }

        // Remove any subscript from the final name value
        name = resolver.getProperty(name);

        // Look up and return this property from our cache
        // creating and adding it to the cache if not found.
        if (name == null) {
            return (null);
        }
        
        PropertyDescriptor[] descriptors = getPropertyDescriptors(bean);
        if (descriptors != null) {
            
            for (int i = 0; i < descriptors.length; i++) {
                if (name.equals(descriptors[i].getName())) {
                    return (descriptors[i]);
                }
            }
        }

        PropertyDescriptor result = null;
        FastHashMap mappedDescriptors =
                getMappedPropertyDescriptors(bean);
        if (mappedDescriptors == null) {
            mappedDescriptors = new FastHashMap();
            mappedDescriptors.setFast(true);
            mappedDescriptorsCache.put(bean.getClass(), mappedDescriptors);
        }
        result = (PropertyDescriptor) mappedDescriptors.get(name);
        if (result == null) {
            // not found, try to create it
            try {
                result = new MappedPropertyDescriptor(name, bean.getClass());
            } catch (IntrospectionException ie) {
                /* Swallow IntrospectionException
                 * TODO: Why?
                 */
            }
            if (result != null) {
                mappedDescriptors.put(name, result);
            }
        }
        
        return result;

    }


    /**
     * <p>Retrieve the property descriptors for the specified class,
     * introspecting and caching them the first time a particular bean class
     * is encountered.</p>
     *
     * <p><strong>FIXME</strong> - Does not work with DynaBeans.</p>
     *
     * @param beanClass Bean class for which property descriptors are requested
     * @return the property descriptors
     *
     * @exception IllegalArgumentException if <code>beanClass</code> is null
     */
    public PropertyDescriptor[]
            getPropertyDescriptors(Class beanClass) {

        if (beanClass == null) {
            throw new IllegalArgumentException("No bean class specified");
        }

        // Look up any cached descriptors for this bean class
        PropertyDescriptor[] descriptors = null;
        descriptors =
                (PropertyDescriptor[]) descriptorsCache.get(beanClass);
        if (descriptors != null) {
            return (descriptors);
        }

        // Introspect the bean and cache the generated descriptors
        BeanInfo beanInfo = null;
        try {
            beanInfo = Introspector.getBeanInfo(beanClass);
        } catch (IntrospectionException e) {
            return (new PropertyDescriptor[0]);
        }
        descriptors = beanInfo.getPropertyDescriptors();
        if (descriptors == null) {
            descriptors = new PropertyDescriptor[0];
        }

        // ----------------- Workaround for Bug 28358 --------- START ------------------
        //
        // The following code fixes an issue where IndexedPropertyDescriptor behaves
        // Differently in different versions of the JDK for 'indexed' properties which
        // use java.util.List (rather than an array).
        //
        // If you have a Bean with the following getters/setters for an indexed property:
        //
        //     public List getFoo()
        //     public Object getFoo(int index)
        //     public void setFoo(List foo)
        //     public void setFoo(int index, Object foo)
        //
        // then the IndexedPropertyDescriptor's getReadMethod() and getWriteMethod()
        // behave as follows:
        //
        //     JDK 1.3.1_04: returns valid Method objects from these methods.
        //     JDK 1.4.2_05: returns null from these methods.
        //
        for (int i = 0; i < descriptors.length; i++) {
            if (descriptors[i] instanceof IndexedPropertyDescriptor) {
                IndexedPropertyDescriptor descriptor =  (IndexedPropertyDescriptor)descriptors[i];
                String propName = descriptor.getName().substring(0, 1).toUpperCase() +
                                  descriptor.getName().substring(1);

                if (descriptor.getReadMethod() == null) {
                    String methodName = descriptor.getIndexedReadMethod() != null
                                        ? descriptor.getIndexedReadMethod().getName()
                                        : "get" + propName;
                    Method readMethod = MethodUtils.getMatchingAccessibleMethod(beanClass,
                                                            methodName,
                                                            EMPTY_CLASS_PARAMETERS);
                    if (readMethod != null) {
                        try {
                            descriptor.setReadMethod(readMethod);
                        } catch(Exception e) {
                            log.error("Error setting indexed property read method", e);
                        }
                    }
                }
                if (descriptor.getWriteMethod() == null) {
                    String methodName = descriptor.getIndexedWriteMethod() != null
                                      ? descriptor.getIndexedWriteMethod().getName()
                                      : "set" + propName;
                    Method writeMethod = MethodUtils.getMatchingAccessibleMethod(beanClass,
                                                            methodName,
                                                            LIST_CLASS_PARAMETER);
                    if (writeMethod == null) {
                        Method[] methods = beanClass.getMethods();
                        for (int j = 0; j < methods.length; j++) {
                            if (methods[j].getName().equals(methodName)) {
                                Class[] parameterTypes = methods[j].getParameterTypes();
                                if (parameterTypes.length == 1 &&
                                    List.class.isAssignableFrom(parameterTypes[0])) {
                                    writeMethod = methods[j];
                                    break; 
                                }
                            }
                        }
                    }
                    if (writeMethod != null) {
                        try {
                            descriptor.setWriteMethod(writeMethod);
                        } catch(Exception e) {
                            log.error("Error setting indexed property write method", e);
                        }
                    }
                }
            }
        }
        // ----------------- Workaround for Bug 28358 ---------- END -------------------

        descriptorsCache.put(beanClass, descriptors);
        return (descriptors);

    }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章