You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by to...@apache.org on 2007/07/18 06:01:21 UTC

svn commit: r557137 - in /harmony/enhanced/classlib/trunk/modules/beans/src: main/java/java/beans/ test/java/org/apache/harmony/beans/tests/java/beans/

Author: tonywu
Date: Tue Jul 17 21:01:20 2007
New Revision: 557137

URL: http://svn.apache.org/viewvc?view=rev&rev=557137
Log:
refactor Introspector, make it easier to understand
1, correct some testcases
2, combine BeanInfoData and BeanInfoWrapper to one class
3, add method merge() in FeatureDescripter and its sub classes

Modified:
    harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/EventSetDescriptor.java
    harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/FeatureDescriptor.java
    harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/Introspector.java
    harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/MethodDescriptor.java
    harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/PropertyDescriptor.java
    harmony/enhanced/classlib/trunk/modules/beans/src/test/java/org/apache/harmony/beans/tests/java/beans/IntrospectorTest.java

Modified: harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/EventSetDescriptor.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/EventSetDescriptor.java?view=diff&rev=557137&r1=557136&r2=557137
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/EventSetDescriptor.java (original)
+++ harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/EventSetDescriptor.java Tue Jul 17 21:01:20 2007
@@ -436,46 +436,27 @@
         return false;
     }
 
+    void merge(EventSetDescriptor event) {
+        super.merge(event);
+        if (addListenerMethod == null) {
+            addListenerMethod = event.addListenerMethod;
+        }
+        if (getListenerMethod == null) {
+            getListenerMethod = event.getListenerMethod;
+        }
+        if (listenerMethodDescriptors == null) {
+            listenerMethodDescriptors = event.listenerMethodDescriptors;
+        }
+        if (listenerMethods == null) {
+            listenerMethods = event.listenerMethods;
+        }
+        if (listenerType == null) {
+            listenerType = event.listenerType;
+        }
 
-//TODO investigate, do we need the following code?
-
-//    private static Method checkRegistrationMethod(Class<?> listenerType,
-//            Method registrationMethod) throws IntrospectionException {
-//        if (registrationMethod == null) {
-//            return null;
-//        }
-//        Class<?> returnType = registrationMethod.getReturnType();
-//        Class<?>[] parameterTypes;
-//        if (returnType != void.class) {
-//            throw new IntrospectionException(Messages.getString(
-//                    "beans.33", registrationMethod.getName())); //$NON-NLS-1$
-//        }
-//        parameterTypes = registrationMethod.getParameterTypes();
-//        if (parameterTypes == null || parameterTypes.length != 1) {
-//            throw new IntrospectionException(Messages.getString(
-//                    "beans.34", registrationMethod.getName())); //$NON-NLS-1$
-//        } else if (parameterTypes[0] != listenerType) {
-//            throw new IntrospectionException(Messages.getString(
-//                    "beans.35", listenerType.getName())); //$NON-NLS-1$
-//        } else {
-//            return registrationMethod;
-//        }
-//    }
-
-//    private static Method checkGetListenerMethod(Class<?> listenerType, Method getListenerMethod)
-//            throws IntrospectionException {
-//        if (getListenerMethod == null) {
-//            return null;
-//        }
-//        Class<?>[] parameterTypes = getListenerMethod.getParameterTypes();
-//        Class<?> returnType;
-//        if (parameterTypes.length != 0) {
-//            throw new IntrospectionException(Messages.getString("beans.36")); //$NON-NLS-1$
-//        }
-//        returnType = getListenerMethod.getReturnType();
-//        if (returnType.isArray() && returnType.getComponentType() == listenerType) {
-//            return getListenerMethod;
-//        }
-//        throw new IntrospectionException(Messages.getString("beans.37")); //$NON-NLS-1$
-//    }
+        if (removeListenerMethod == null) {
+            removeListenerMethod = event.removeListenerMethod;
+        }
+        inDefaultEventSet &= event.inDefaultEventSet;
+    }
 }

Modified: harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/FeatureDescriptor.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/FeatureDescriptor.java?view=diff&rev=557137&r1=557136&r2=557137
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/FeatureDescriptor.java (original)
+++ harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/FeatureDescriptor.java Tue Jul 17 21:01:20 2007
@@ -231,4 +231,20 @@
     public boolean isExpert() {
         return expert;
     }
+    
+    void merge(FeatureDescriptor feature){
+        assert(name.equals(feature.name));
+        expert |= feature.expert;
+        hidden |= feature.hidden;
+        preferred |= feature.preferred;
+        if(shortDescription == null){
+            shortDescription = feature.shortDescription;
+        }
+        if(name == null){
+            name = feature.name;
+        }
+        if(displayName == null){
+            displayName = feature.displayName;
+        }        
+    }
 }

Modified: harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/Introspector.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/Introspector.java?view=diff&rev=557137&r1=557136&r2=557137
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/Introspector.java (original)
+++ harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/Introspector.java Tue Jul 17 21:01:20 2007
@@ -17,246 +17,329 @@
 
 package java.beans;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
+import java.util.Collections;
 import java.util.Map;
+import java.util.WeakHashMap;
 
-import org.apache.harmony.beans.internal.nls.Messages;
-
+/**
+ * The <code>Introspector</code> is a utility for developers to figure out
+ * which properties, events, and methods a JavaBean supports.
+ * <p>
+ * The <code>Introspector</code> class walks over the class/superclass chain
+ * of the target bean class. At each level it checks if there is a matching
+ * <code>BeanInfo</code> class which provides explicit information about the
+ * bean, and if so uses that explicit information. Otherwise it uses the low
+ * level reflection APIs to study the target class and uses design patterns to
+ * analyze its behaviour and then proceeds to continue the introspection with
+ * its baseclass.
+ * </p>
+ * <p>
+ * To look for the explicit information of a bean:
+ * </p>
+ * <ol>
+ * <li>The <code>Introspector</code> appends "BeanInfo" to the qualified name
+ * of the bean class, try to use the new class as the "BeanInfo" class. If the
+ * "BeanInfo" class exsits and returns non-null value when queried for explicit
+ * information, use the explicit information</li>
+ * <li>If the first step fails, the <code>Introspector</code> will extract a
+ * simple class name of the bean class by removing the package name from the
+ * qualified name of the bean class, append "BeanInfo" to it. And look for the
+ * simple class name in the packages defined in the "BeanInfo" search path (The
+ * default "BeanInfo" search path is <code>sun.beans.infos</code>). If it
+ * finds a "BeanInfo" class and the "BeanInfo" class returns non-null value when
+ * queried for explicit information, use the explicit information</li>
+ * </ol>
+ * 
+ */
+//ScrollPane cannot be introspected correctly
+public class Introspector extends java.lang.Object {
+
+    // Public fields
+    /**
+     * Constant values to indicate that the <code>Introspector</code> will
+     * ignore all <code>BeanInfo</code> class.
+     */
+    public static final int IGNORE_ALL_BEANINFO = 3;
 
-public class Introspector {
+    /**
+     * Constant values to indicate that the <code>Introspector</code> will
+     * ignore the <code>BeanInfo</code> class of the current bean class.
+     */
+    public static final int IGNORE_IMMEDIATE_BEANINFO = 2;
 
+    /**
+     * Constant values to indicate that the <code>Introspector</code> will use
+     * all <code>BeanInfo</code> class which have been found. This is the default one.
+     */
     public static final int USE_ALL_BEANINFO = 1;
 
-    public static final int IGNORE_IMMEDIATE_BEANINFO = 2;
+    // Default search path for BeanInfo classes
+    private static final String DEFAULT_BEANINFO_SEARCHPATH = "sun.beans.infos"; //$NON-NLS-1$
 
-    public static final int IGNORE_ALL_BEANINFO = 3;
+    // The search path to use to find BeanInfo classes
+    // - an array of package names that are used in turn
+    private static String[] searchPath = { DEFAULT_BEANINFO_SEARCHPATH };
+
+    // The cache to store Bean Info objects that have been found or created
+    private static final int DEFAULT_CAPACITY = 128;
+
+    private static Map<Class, StandardBeanInfo> theCache = Collections.synchronizedMap(new WeakHashMap<Class, StandardBeanInfo>(DEFAULT_CAPACITY));
 
     private Introspector() {
+        super();
     }
 
+    /**
+     * Decapitalizes a given string according to the rule:
+     * <ul>
+     * <li>If the first or only character is Upper Case, it is made Lower Case
+     * <li>UNLESS the second character is also Upper Case, when the String is
+     * returned unchanged <eul>
+     * 
+     * @param name -
+     *            the String to decapitalize
+     * @return the decapitalized version of the String
+     */
     public static String decapitalize(String name) {
-        if ((name != null) && (name.length() > 0)) {
-            String result;
-            
-            // first two letters are capital
-            if ((name.length() > 1)
-                    && Character.isUpperCase(name.charAt(0))
-                    && Character.isUpperCase(name.charAt(1))) {
-                return name;
-            }
-            
-            result = name.substring(0, 1).toLowerCase();
-            if (name.length() > 1) {
-                result += name.substring(1);
-            }
-            
-            return result;
-        }
-        return name;
-    }
 
-    public static BeanInfo getBeanInfo(Class<?> beanClass, int flags)
-            throws IntrospectionException {
-        switch (flags) {
-            case USE_ALL_BEANINFO:
-                return getBeanInfo(beanClass, null, false, false);
-            case IGNORE_IMMEDIATE_BEANINFO:
-                return getBeanInfo(beanClass, null, true, false);
-            case IGNORE_ALL_BEANINFO:
-                return getBeanInfo(beanClass, null, true, true);
-            default:
-                // TODO: verify that default behavior complies with RI
-                return getBeanInfo(beanClass, null, false, false);
+        if (name == null)
+            return null;
+        // The rule for decapitalize is that:
+        // If the first letter of the string is Upper Case, make it lower case
+        // UNLESS the second letter of the string is also Upper Case, in which case no
+        // changes are made.
+        if (name.length() == 0 || (name.length() > 1 && Character.isUpperCase(name.charAt(1)))) {
+            return name;
         }
+        
+        char[] chars = name.toCharArray();
+        chars[0] = Character.toLowerCase(chars[0]);
+        return new String(chars);
     }
 
-    public static BeanInfo getBeanInfo(Class<?> beanClass)
+    /**
+     * Flushes all <code>BeanInfo</code> caches.
+     *  
+     */
+    public static void flushCaches() {
+        // Flush the cache by throwing away the cache HashMap and creating a
+        // new empty one
+        theCache.clear();
+    }
+
+    /**
+     * Flushes the <code>BeanInfo</code> caches of the specified bean class
+     * 
+     * @param clazz
+     *            the specified bean class
+     */
+    public static void flushFromCaches(Class clazz) {
+        if(clazz == null){
+            throw new NullPointerException();
+        }
+        theCache.remove(clazz);
+    }
+
+    /**
+	 * Gets the <code>BeanInfo</code> object which contains the information of
+	 * the properties, events and methods of the specified bean class.
+	 * 
+	 * <p>
+	 * The <code>Introspector</code> will cache the <code>BeanInfo</code>
+	 * object. Subsequent calls to this method will be answered with the cached
+	 * data.
+	 * </p>
+	 * 
+	 * @param beanClass
+	 *            the specified bean class.
+	 * @return the <code>BeanInfo</code> of the bean class.
+	 * @throws IntrospectionException
+	 */
+    public static BeanInfo getBeanInfo(Class beanClass)
             throws IntrospectionException {
-        return getBeanInfo(beanClass, null, false, false);
-    }
-
-    public static BeanInfo getBeanInfo(Class<?> beanClass, Class<?> stopClass)
+        StandardBeanInfo beanInfo = theCache.get(beanClass);
+        if (beanInfo == null) {
+            beanInfo = getBeanInfoImpl(beanClass, null, USE_ALL_BEANINFO);
+            theCache.put(beanClass, beanInfo);
+        }
+        return beanInfo;
+    }
+
+    /**
+     * Gets the <code>BeanInfo</code> object which contains the information of
+     * the properties, events and methods of the specified bean class. It will
+     * not introspect the "stopclass" and its super class.
+     * 
+     * <p>
+     * The <code>Introspector</code> will cache the <code>BeanInfo</code>
+     * object. Subsequent calls to this method will be answered with the cached
+     * data.
+     * </p>
+     * 
+     * @param beanClass
+     *            the specified beanClass.
+     * @param stopClass
+     *            the sopt class which should be super class of the bean class.
+     *            May be null.
+     * @return the <code>BeanInfo</code> of the bean class.
+     * @throws IntrospectionException
+     */
+    public static BeanInfo getBeanInfo(Class beanClass, Class stopClass)
             throws IntrospectionException {
-        return getBeanInfo(beanClass, stopClass, false, false);
-    }
-
-    public static void setBeanInfoSearchPath(String[] searchPath) {
-        SecurityManager sm = System.getSecurityManager();
-
-        if (sm != null) {
-            sm.checkPropertiesAccess();
-        }
-        synchronized(Introspector.class) {
-            path = searchPath;
+        if(stopClass == null){
+            //try to use cache
+            return getBeanInfo(beanClass);
+        }
+        return getBeanInfoImpl(beanClass, stopClass, USE_ALL_BEANINFO);
+    }
+
+    /**
+     * Gets the <code>BeanInfo</code> object which contains the information of
+     * the properties, events and methods of the specified bean class.
+     * <ol>
+     * <li>If <code>flag==IGNORE_ALL_BEANINFO</code>, the
+     * <code>Introspector</code> will ignore all <code>BeanInfo</code>
+     * class.</li>
+     * <li>If <code>flag==IGNORE_IMMEDIATE_BEANINFO</code>, the
+     * <code>Introspector</code> will ignore the <code>BeanInfo</code> class
+     * of the current bean class.</li>
+     * <li>If <code>flag==USE_ALL_BEANINFO</code>, the
+     * <code>Introspector</code> will use all <code>BeanInfo</code> class
+     * which have been found.</li>
+     * </ol>
+     * <p>
+	 * The <code>Introspector</code> will cache the <code>BeanInfo</code>
+	 * object. Subsequent calls to this method will be answered with the cached
+	 * data.
+     * </p>
+     * 
+     * @param beanClass
+     *            the specified bean class.
+     * @param flags
+     *            the flag to control the usage of the explicit
+     *            <code>BeanInfo</code> class.
+     * @return the <code>BeanInfo</code> of the bean class.
+     * @throws IntrospectionException
+     */
+    public static BeanInfo getBeanInfo(Class beanClass, int flags)
+            throws IntrospectionException {
+        if(flags == USE_ALL_BEANINFO){
+            //try to use cache            
+            return getBeanInfo(beanClass);
+        }
+        return getBeanInfoImpl(beanClass, null, flags);
+    }
+
+    /**
+     * Gets an array of search packages.
+     * 
+     * @return an array of search packages.
+     */
+    public static String[] getBeanInfoSearchPath() {
+        String[] path = new String[searchPath.length];
+        System.arraycopy(searchPath, 0, path, 0, searchPath.length);
+        return path;
+    }
+
+    /**
+     * Sets the search packages.
+     * 
+     * @param path the new search packages to be set.
+     */
+    public static void setBeanInfoSearchPath(String[] path) {
+        if (System.getSecurityManager() != null) {
+            System.getSecurityManager().checkPropertiesAccess();
+        }
+        searchPath = path;
+    }
+
+    private static StandardBeanInfo getBeanInfoImpl(Class beanClass, Class stopClass,
+            int flags) throws IntrospectionException {
+        BeanInfo explicitInfo = null;
+        if (flags == USE_ALL_BEANINFO) {
+            explicitInfo = getExplicitBeanInfo(beanClass);
+        }
+        StandardBeanInfo beanInfo = new StandardBeanInfo(beanClass, explicitInfo);
+
+        // recursive get beaninfo for super classes
+        Class beanSuperClass = beanClass.getSuperclass();
+        if (beanSuperClass != stopClass) {
+            if (beanSuperClass == null)
+                throw new IntrospectionException(
+                        "Stop class is not super class of bean class");
+            int superflags = flags == IGNORE_IMMEDIATE_BEANINFO ? USE_ALL_BEANINFO
+                    : flags;
+            BeanInfo superBeanInfo = getBeanInfoImpl(beanSuperClass, stopClass,
+                    superflags);
+            if (superBeanInfo != null) {
+                beanInfo.mergeBeanInfo(superBeanInfo);
+            }
         }
-    }
-
-    public static synchronized String[] getBeanInfoSearchPath() {
-        // compatible with RI
-        if (path == null) {
-            throw new NullPointerException(
-                    Messages.getString("beans.4F")); //$NON-NLS-1$
+        if (beanInfo.additionalBeanInfo != null) {
+            for (BeanInfo info : beanInfo.additionalBeanInfo) {
+                beanInfo.mergeBeanInfo(info, true);
+            }
         }
-
-        return path.clone();
+        return beanInfo;
     }
 
-    public static void flushFromCaches(Class<?> clz) {
-        removeBeanInfoClassFromCache(clz);
-    }
-
-    public static void flushCaches() {
-        removeAllBeanInfoClassesFromCache();
-    }
-
-    // private methods
-
-    private static BeanInfoWrapper getBeanInfo(Class<?> beanClass,
-            Class<?> stopClass, boolean ignoreBeanClassBeanInfo,
-            boolean ignoreSuperClassBeanInfo) throws IntrospectionException {
-        BeanInfoWrapper beanInfoWrapper;
-        BeanInfo beanInfo;
-        BeanInfoImpl beanInfoImpl;
-        BeanInfoWrapper wrapper;
-        Class<?> parent;
-        
-        if (beanClass == null) {
-            throw new java.lang.NullPointerException();
-        }
-        
-        if (stopClass != null && !stopClass.isAssignableFrom(beanClass)) {
-            throw new IntrospectionException(
-                    Messages.getString("beans.4E")); //$NON-NLS-1$
-        }
-
-        beanInfoWrapper = findBeanInfoClassInCache(beanClass,
-                stopClass, ignoreBeanClassBeanInfo, ignoreSuperClassBeanInfo);
-
-        if (beanInfoWrapper != null) {
-            return beanInfoWrapper;
-        }
-
-        // find bean info as a separate class
-
-        beanInfo = null;
-
-        if (!ignoreBeanClassBeanInfo) {
-            try {
-                Class<?> beanInfoClass = findBeanInfoClass(beanClass);
-
-                if (beanInfoClass != null) {
-                    beanInfo = (BeanInfo) beanInfoClass.newInstance();
-                }
-            } catch (Exception e) {
+    private static BeanInfo getExplicitBeanInfo(Class beanClass) {
+        BeanInfo theBeanInfo = null;
+        String beanInfoClassName = beanClass.getName() + "BeanInfo"; //$NON-NLS-1$
+        try{
+            theBeanInfo = loadBeanInfo(beanInfoClassName, beanClass);
+            return theBeanInfo;
+        }catch(Exception e){
+            //fall through
+        }
+        int index = beanInfoClassName.lastIndexOf('.');
+        String beanInfoName = index>=0? beanInfoClassName.substring(index):beanInfoClassName;
+        for (int i = 0; i < searchPath.length; i++) {
+            beanInfoClassName = searchPath[i] + "." + beanInfoName;
+            try{
+                theBeanInfo = loadBeanInfo(beanInfoClassName, beanClass);
+                break;
+            }catch(Exception e){
+                //ignore, try next one
             }
         }
-
-        // ...
-
-        // generate bean info automatically
-
-        beanInfoImpl = new BeanInfoImpl(beanClass);
-
-        // ...
-
-        wrapper = new BeanInfoWrapper(beanInfo, beanInfoImpl);
-        parent = beanClass.getSuperclass();
-        
-        if (parent != null && parent != stopClass) {
-            BeanInfoWrapper parentBeanInfo = getBeanInfo(parent, stopClass,
-                    ignoreSuperClassBeanInfo, ignoreSuperClassBeanInfo);
-
-            wrapper.setParentToMerge(parentBeanInfo);
-        }
-
-        // ...
-
-        storeBeanInfoClassInCache(wrapper, beanClass, stopClass,
-                ignoreBeanClassBeanInfo, ignoreSuperClassBeanInfo);
-        
-        return wrapper;
+        return theBeanInfo;
     }
 
-    private static Class<?> findBeanInfoClass(Class<?> beanClass) {
-        String beanClassName = beanClass.getName();
-        int idx = beanClassName.lastIndexOf("."); //$NON-NLS-1$
-        String shortBeanInfoClassName = beanClassName.substring(idx + 1,
-                beanClassName.length())
-                + "BeanInfo"; //$NON-NLS-1$
-        String fullBeanInfoClassName = beanClassName + "BeanInfo"; //$NON-NLS-1$
 
-        Class<?> beanInfoClass = null;
+    /*
+     * Method which attempts to instantiate a BeanInfo object of the supplied
+     * classname
+     * 
+     * @param theBeanInfoClassName -
+     *            the Class Name of the class of which the BeanInfo is an
+     *            instance
+     * @param classLoader
+     * @return A BeanInfo object which is an instance of the Class named
+     *         theBeanInfoClassName null if the Class does not exist or if there
+     *         are problems instantiating the instance
+     */
+    private static BeanInfo loadBeanInfo(String beanInfoClassName,
+        Class beanClass) throws Exception{
         try {
-            beanInfoClass = Class.forName(fullBeanInfoClassName, true,
-                    beanClass.getClassLoader());
-
-        } catch (ClassNotFoundException cnfe) {
-            for (String element : path) {
-                try {
-                    fullBeanInfoClassName = element + "." //$NON-NLS-1$
-                            + shortBeanInfoClassName;
-                    beanInfoClass = Class.forName(fullBeanInfoClassName, true,
-                            beanClass.getClassLoader());
-                    break;
-                } catch (ClassNotFoundException cnfe2) {
-                }
-            }
+            return (BeanInfo) Class.forName(beanInfoClassName, true,
+                    beanClass.getClassLoader()).newInstance();
+        } catch (Exception e) {
+            // fall through
         }
-
-        return beanInfoClass;
-    }
-
-    private static BeanInfoWrapper findBeanInfoClassInCache(Class<?> beanClass,
-            Class<?> stopClass, boolean ignoreBeanClassBeanInfo,
-            boolean ignoreSuperClassBeanInfo) {
-        BeanInfoWrapper result = null;
-        List<BeanInfoData> beanInfoDatas = beanInfos.get(beanClass.getName());
-        if (beanInfoDatas != null) {
-            Iterator<BeanInfoData> iterator = beanInfoDatas.iterator();
-            while (iterator.hasNext()) {
-                BeanInfoData beanInfoData = iterator.next();
-                if ((beanInfoData.getStopClass() == stopClass)
-                        && (beanInfoData.getIgnoreBeanClassBeanInfo() == ignoreBeanClassBeanInfo)
-                        && (beanInfoData.getIgnoreSuperClassBeanInfo() == ignoreSuperClassBeanInfo)) {
-                    result = beanInfoData.getBeanInfoWrapper();
-                }
-                if (result != null) {
-                    break;
-                }
-            }
-        }
-        return result;
-    }
-
-    private static void storeBeanInfoClassInCache(
-            BeanInfoWrapper beanInfoWrapper, Class<?> beanClass,
-            Class<?> stopClass, boolean ignoreBeanClassBeanInfo,
-            boolean ignoreSuperClassBeanInfo) {
-        List<BeanInfoData> beanInfoDatas = beanInfos.get(beanClass.getName());
-        if (beanInfoDatas == null) {
-            beanInfoDatas = new ArrayList<BeanInfoData>();
-            beanInfos.put(beanClass.getName(), beanInfoDatas);
+        try {
+            return (BeanInfo) Class.forName(beanInfoClassName, true,
+                    ClassLoader.getSystemClassLoader()).newInstance();
+        } catch (Exception e) {
+            // fall through
         }
-        beanInfoDatas.add(new BeanInfoData(stopClass, ignoreBeanClassBeanInfo,
-                ignoreSuperClassBeanInfo, beanInfoWrapper));
-    }
-
-    private static void removeBeanInfoClassFromCache(Class<?> beanClass) {
-        beanInfos.remove(beanClass.getName());
+        return (BeanInfo) Class.forName(beanInfoClassName, true,
+                Thread.currentThread().getContextClassLoader()).newInstance();
     }
+    
+    
 
-    private static void removeAllBeanInfoClassesFromCache() {
-        beanInfos.clear();
-    }
-
-    // private fields
+}
 
-    private static String[] path = { "org.apache.harmony.beans.infos" }; //$NON-NLS-1$
 
-    private static final Map<String, List<BeanInfoData>> beanInfos =
-            new HashMap<String, List<BeanInfoData>>();
 
-}

Modified: harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/MethodDescriptor.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/MethodDescriptor.java?view=diff&rev=557137&r1=557136&r2=557137
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/MethodDescriptor.java (original)
+++ harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/MethodDescriptor.java Tue Jul 17 21:01:20 2007
@@ -96,4 +96,14 @@
     public ParameterDescriptor[] getParameterDescriptors() {
         return parameterDescriptors;
     }
+    
+    void merge(MethodDescriptor anotherMethod){
+        super.merge(anotherMethod);
+        if(method == null){
+            method = anotherMethod.method;
+        }
+        if(parameterDescriptors == null){
+            parameterDescriptors = anotherMethod.parameterDescriptors;
+        }
+    }
 }

Modified: harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/PropertyDescriptor.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/PropertyDescriptor.java?view=diff&rev=557137&r1=557136&r2=557137
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/PropertyDescriptor.java (original)
+++ harmony/enhanced/classlib/trunk/modules/beans/src/main/java/java/beans/PropertyDescriptor.java Tue Jul 17 21:01:20 2007
@@ -31,9 +31,9 @@
 
     private Class<?> propertyEditorClass;
 
-    private boolean constrained;
+    boolean constrained;
 
-    private boolean bound;
+    boolean bound;
 
     public PropertyDescriptor(String propertyName, Class<?> beanClass, String getterName,
             String setterName) throws IntrospectionException {

Modified: harmony/enhanced/classlib/trunk/modules/beans/src/test/java/org/apache/harmony/beans/tests/java/beans/IntrospectorTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/beans/src/test/java/org/apache/harmony/beans/tests/java/beans/IntrospectorTest.java?view=diff&rev=557137&r1=557136&r2=557137
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/beans/src/test/java/org/apache/harmony/beans/tests/java/beans/IntrospectorTest.java (original)
+++ harmony/enhanced/classlib/trunk/modules/beans/src/test/java/org/apache/harmony/beans/tests/java/beans/IntrospectorTest.java Tue Jul 17 21:01:20 2007
@@ -26,6 +26,7 @@
 import java.beans.MethodDescriptor;
 import java.beans.PropertyDescriptor;
 import java.beans.SimpleBeanInfo;
+import java.io.Serializable;
 import java.lang.reflect.Method;
 import java.security.Permission;
 import java.util.ArrayList;
@@ -125,9 +126,6 @@
         MethodDescriptor[] mds = info.getMethodDescriptors();
         assertNotNull(mds);
         assertEquals(11, mds.length);
-        assertEquals("wait", mds[8].getName());
-        assertEquals("wait", mds[9].getName());
-        assertEquals("wait", mds[10].getName());
     }
 
     /**
@@ -279,9 +277,10 @@
      */
     public void testAdditionalBeanInfo() throws IntrospectionException {
         BeanInfo info = Introspector.getBeanInfo(StandardBean2.class);
+        assertNull(info.getAdditionalBeanInfo());
         PropertyDescriptor[] pds = info.getPropertyDescriptors();
-        assertEquals(1, pds.length);
-        assertEquals("grannyText", pds[0].getName());
+        assertEquals(2, pds.length);
+        assertEquals("class", pds[0].getName());
     }
 
     /**
@@ -437,6 +436,12 @@
         assertTrue(contains("setName", mds));
         assertTrue(contains("getComplexLabel", mds));
         assertTrue(contains("setComplexLabel", mds));
+        try{
+            BeanInfo info2 = Introspector.getBeanInfo(MockFoo.class,
+                    Serializable.class);
+            fail("Shoule throw exception, stopclass must be superclass of given bean");
+        }catch(IntrospectionException e){
+        }
     }
 
     public void testGetBeanInfoClassClass_StopNull()
@@ -666,11 +671,28 @@
             assertEquals(pds[i], pds2[i]);
         }
     }
+    
+    public void testSetBeanInfoSearchPath_null() throws IntrospectionException{
+        String[] oldPath = Introspector.getBeanInfoSearchPath();
+        try{
+            Introspector.setBeanInfoSearchPath(null);
+            try{
+                Introspector.getBeanInfoSearchPath();
+                fail("should throw NPE");
+            }catch(NullPointerException e){
+            }
+            String[] newPath = new String[]{"mock", null, ""};
+            Introspector.setBeanInfoSearchPath(newPath);
+            Introspector.getBeanInfo(this.getClass());
+        }finally{
+            Introspector.setBeanInfoSearchPath(oldPath);
+        }
+    }
 
     public void testGetBeanInfoSearchPath() {
         String[] path = Introspector.getBeanInfoSearchPath();
         assertEquals(1, path.length);
-        assertEquals("org.apache.harmony.beans.infos", path[0]);
+        assertTrue(path[0].endsWith("beans.infos"));
     }
 
     public void testGetBeanInfoSearchPath_Default()
@@ -679,11 +701,11 @@
         PropertyDescriptor[] pds = info.getPropertyDescriptors();
         BeanDescriptor beanDesc;
 
-        assertEquals(1, pds.length);
-        assertEquals("text.MockFooButtonBeanInfo", pds[0].getName());
+        assertEquals(2, pds.length);
+        assertEquals("class", pds[0].getName());
 
         beanDesc = info.getBeanDescriptor();
-        assertEquals("MockFooButton.MockFooButtonBeanInfo", beanDesc.getName());
+        assertEquals("MockFooButton", beanDesc.getName());
     }
 
     public void testSetBeanInfoSearchPath() throws IntrospectionException {
@@ -809,10 +831,10 @@
                 assertNotNull(element.getReadMethod());
             } else {
                 assertEquals("fox301", element.getName());
-                assertEquals(String.class.getName(), element
+                assertEquals(Integer.class.getName(), element
                         .getPropertyType().getName());
-                assertNotNull(element.getWriteMethod());
-                assertNull(element.getReadMethod());
+                assertNull(element.getWriteMethod());
+                assertNotNull(element.getReadMethod());
             }
         }
     }