private static Map createProperties(Class clazz)
        throws IntrospectionException {

        Map properties = new HashMap();

        if (clazz == null || clazz.isPrimitive()) {
            return properties;
        }

        BeanInfo info;
        try {
            info = Introspector.getBeanInfo(clazz);
        }
        catch (LinkageError e) {
            throw new IntrospectionException(e.toString());
        }

        if (info != null) {
            PropertyDescriptor[] pdArray = info.getPropertyDescriptors();

            // Standard properties.
            int length = pdArray.length;
            for (int i=0; i<length; i++) {
                properties.put(pdArray[i].getName(), pdArray[i]);
            }
        }

        // Properties defined in Object are also available to interfaces.
        if (clazz.isInterface()) {
            properties.putAll(getAllProperties(Object.class));
        }

        // Ensure that all implemented interfaces are properly analyzed.
        Class[] interfaces = clazz.getInterfaces();
        for (int i=0; i<interfaces.length; i++) {
            properties.putAll(getAllProperties(interfaces[i]));
        }

        // Filter out properties with names that contain '$' characters.
        Iterator it = properties.keySet().iterator();
        while (it.hasNext()) {
            String propertyName = (String)it.next();
            if (propertyName.indexOf('$') >= 0) {
                it.remove();
            }
        }

        return properties;
    }