logback-android/src/main/java/ch/qos/logback/core/joran/util/Introspector.java
static public PropertyDescriptor[] getPropertyDescriptors(Class<?> clazz) {
    final String SETTER_PREFIX = "set";
    final String GETTER_PREFIX = "get";
    final int LEN_PREFIX = SETTER_PREFIX.length();

    Map<String, PropertyDescriptor> map = new HashMap<String, PropertyDescriptor>();
    for (Method m : clazz.getMethods()) {
      PropertyDescriptor pd = null;
      String mName = m.getName();

      boolean isGet = mName.startsWith(GETTER_PREFIX) && (mName.length() > LEN_PREFIX);
      boolean isSet = mName.startsWith(SETTER_PREFIX) && (mName.length() > LEN_PREFIX);

      if (isGet || isSet) {
        String propName = decapitalize(mName.substring(LEN_PREFIX));
        
        pd = map.get(propName);
        if (pd == null) {
          pd = new PropertyDescriptor(propName);
          map.put(propName, pd);
        }

        Class<?>[] parmTypes = m.getParameterTypes();
        if (isSet) {
          if (parmTypes.length == 1) { // we only want the single-parm setter
            pd.setWriteMethod(m);
            pd.setPropertyType(parmTypes[0]);
          }
        } else if (isGet) {
          if (parmTypes.length == 0) { // we only want the zero-parm getter
            pd.setReadMethod(m);

            // let setter's type take priority
            if (pd.getPropertyType() == null) {
              pd.setPropertyType(m.getReturnType());
            }
          }
        }
      }
    }

    return map.values().toArray(new PropertyDescriptor[0]);
  }
static public PropertyDescriptor[] getPropertyDescriptors(Class<?> clazz) {
    final String SETTER_PREFIX = "set";
    final String GETTER_PREFIX = "get";
    final int LEN_PREFIX = SETTER_PREFIX.length();

    Map<String, PropertyDescriptor> map = new HashMap<String, PropertyDescriptor>();
    for (Method m : clazz.getMethods()) {
      PropertyDescriptor pd = null;
      String mName = m.getName();

      boolean isGet = mName.startsWith(GETTER_PREFIX) && (mName.length() > LEN_PREFIX);
      boolean isSet = mName.startsWith(SETTER_PREFIX) && (mName.length() > LEN_PREFIX);

      if (isGet || isSet) {
        String propName = decapitalize(mName.substring(LEN_PREFIX));
        
        pd = map.get(propName);
        if (pd == null) {
          pd = new PropertyDescriptor(propName);
          map.put(propName, pd);
        }

        Class<?>[] parmTypes = m.getParameterTypes();
        if (isSet) {
          if (parmTypes.length == 1) { // we only want the single-parm setter
            pd.setWriteMethod(m);
            pd.setPropertyType(parmTypes[0]);
          }
        } else if (isGet) {
          if (parmTypes.length == 0) { // we only want the zero-parm getter
            pd.setReadMethod(m);

            // let setter's type take priority
            if (pd.getPropertyType() == null) {
              pd.setPropertyType(m.getReturnType());
            }
          }
        }
      }
    }

    return map.values().toArray(new PropertyDescriptor[0]);
  }
Gets a class's property descriptors. All properties have methods whose name
begins with "set" or "get". The setters must have a single parameter and
getters must have none.

@param clazz
class to be evaluated
@return property descriptors