Example usage for java.lang.reflect Modifier isStatic

List of usage examples for java.lang.reflect Modifier isStatic

Introduction

In this page you can find the example usage for java.lang.reflect Modifier isStatic.

Prototype

public static boolean isStatic(int mod) 

Source Link

Document

Return true if the integer argument includes the static modifier, false otherwise.

Usage

From source file:org.brushingbits.jnap.struts2.config.RestControllerConfigBuilder.java

/**
 * TODO//from  ww  w  . j  a  v a  2 s.co m
 * 
 * @param controllerClass The <code>Controller</code> class to search methods for.
 * @return a map containing the method's name as the key and its configuration as the value.
 * 
 * @see org.apache.struts2.convention.annotation.Action
 * @see javax.ws.rs.Path
 * @see javax.ws.rs.HttpMethod
 * @see javax.ws.rs.GET
 * @see javax.ws.rs.POST
 * @see javax.ws.rs.PUT
 * @see javax.ws.rs.DELETE
 * @see javax.ws.rs.Consumes
 * @see javax.ws.rs.Produces
 */
protected Map<String, ActionMethodConfigBean> findActionMethods(Class<?> controllerClass) {
    Map<String, ActionMethodConfigBean> map = new HashMap<String, ActionMethodConfigBean>();
    Method[] methods = controllerClass.getMethods();
    for (Method method : methods) {

        // first of all, lets validate the candidate...
        Class<?> returnType = method.getReturnType();
        if (returnType == null
                || (!returnType.equals(String.class) && !returnType.isAssignableFrom(Response.class))
                || method.getParameterTypes().length > 0 || Modifier.isStatic(method.getModifiers())) {
            continue;
        }

        ActionMethodConfigBean methodConfig = new ActionMethodConfigBean();
        methodConfig.setName(method.getName());

        // Guessing http method
        String httpMethod = this.guessHttpMethod(method).value();
        methodConfig.setHttpMethod(httpMethod);

        // if a @Action annotation is found then keep it for results, interceptors and so to be configured properly
        final Action actionAnnotation = ReflectionUtils.getAnnotation(Action.class, method);
        if (actionAnnotation != null) {
            methodConfig.setAction(actionAnnotation);
            methodConfig.setUriTemplate(actionAnnotation.value().trim());
        }

        // if a @Path annotation is found then its value overwrites the @Action one (if found too)
        final Path pathAnnotation = ReflectionUtils.getAnnotation(Path.class, method);
        if (pathAnnotation != null) {
            methodConfig.setUriTemplate(pathAnnotation.value().trim());
        }

        // are there any restrinctions for response type
        //         methodConfig.setProduces(method.getAnnotation(Produces.class));
        // TODO @Consumes

        // if no URI template found, then guess based on method's name
        if (StringUtils.isBlank(methodConfig.getUriTemplate())) {
            // TODO filter methods
            //methodConfig.setUriTemplate(actionNameBuilder.build(method.getName()));
        } else {
            map.put(method.getName(), methodConfig);
        }

        //         map.put(method.getName(), methodConfig); TODO remove 'else' above after impl method filtering
    }
    return map;
}

From source file:com.googlecode.ehcache.annotations.key.AbstractDeepCacheKeyGenerator.java

/**
 * Calls {@link #shouldReflect(Object)} to determine if the object needs to be reflected on to
 * generate a good key. If so {@link AccessibleObject#setAccessible(AccessibleObject[], boolean)} is
 * used to enable access to private, protected and default fields. Each non-transient, non-static field
 * has {@link #deepHashCode(Object, Object)} called on it.
 */// ww w .java  2  s.c o m
protected final void reflectionDeepHashCode(G generator, final Object element) {
    //Special objects which shouldn't be reflected on due to lack of interesting fields
    if (element instanceof Class<?>) {
        this.append(generator, element);
        return;
    }

    //Determine if the element should be reflected on
    if (!this.shouldReflect(element)) {
        this.append(generator, element);
        return;
    }

    //Accumulate the data that makes up the object being reflected on so it can be recursed on as a single grouping of data
    final List<Object> reflectiveObject = new LinkedList<Object>();

    //Write out the target class so that two classes with the same fields can't collide
    reflectiveObject.add(element.getClass());

    try {
        for (Class<?> targetClass = element.getClass(); targetClass != null; targetClass = targetClass
                .getSuperclass()) {
            final Field[] fields = targetClass.getDeclaredFields();
            AccessibleObject.setAccessible(fields, true);

            for (int i = 0; i < fields.length; i++) {
                final Field field = fields[i];
                final int modifiers = field.getModifiers();

                //Ignore static and transient fields
                if (!Modifier.isStatic(modifiers) && !Modifier.isTransient(modifiers)) {
                    final Object fieldValue = field.get(element);
                    reflectiveObject.add(fieldValue);
                }
            }
        }
    } catch (IllegalAccessException exception) {
        ReflectionUtils.handleReflectionException(exception);
    }

    this.deepHashCode(generator, reflectiveObject);
}

From source file:io.mandrel.OtherTest.java

public void inspect(int level, Type clazz, String name) {

    if (level > 6)
        return;//  ww w .ja  v  a 2  s .  c om

    if (clazz instanceof Class && !((Class<?>) clazz).isEnum() && ((Class<?>) clazz).getPackage() != null
            && ((Class<?>) clazz).getPackage().getName().startsWith("io.mandrel")) {
        int newLevel = level + 1;
        Field[] fields = ((Class<?>) clazz).getDeclaredFields();

        for (Field field : fields) {
            Class<?> fieldType = field.getType();
            String text;
            if (!field.isAnnotationPresent(JsonIgnore.class) && !Modifier.isStatic(field.getModifiers())) {
                if (List.class.equals(fieldType) || Map.class.equals(fieldType)) {
                    Type type = field.getGenericType();
                    if (type instanceof ParameterizedType) {
                        ParameterizedType pType = (ParameterizedType) type;
                        Type paramType = pType.getActualTypeArguments()[pType.getActualTypeArguments().length
                                - 1];

                        text = field.getName() + "(container of " + paramType + ")";
                        System.err.println(StringUtils.leftPad(text, text.length() + newLevel * 5, "\t-   "));
                        inspect(newLevel, paramType, "");
                    }
                } else {
                    text = field.getName()
                            + (field.getType().isPrimitive() || field.getType().equals(String.class)
                                    || field.getType().equals(LocalDateTime.class)
                                            ? " (" + field.getType().getName() + ")"
                                            : "");
                    System.err.println(StringUtils.leftPad(text, text.length() + newLevel * 5, "\t-   "));
                    inspect(newLevel, fieldType, field.getName());
                }

                // JsonSubTypes subtype =
                // fieldType.getAnnotation(JsonSubTypes.class);
                // if (subtype != null) {
                // int subLevel = level + 2;
                // text = "subtypes:";
                // System.err.println(StringUtils.leftPad(text,
                // text.length() + subLevel * 5, "\t-   "));
                // for (JsonSubTypes.Type type : subtype.value()) {
                // text = "subtype:" + type.name();
                // System.err.println(StringUtils.leftPad(text,
                // text.length() + (subLevel + 1) * 5, "\t-   "));
                // inspect((subLevel + 1), type.value(), type.name());
                // }
                // }
            }
        }

        JsonSubTypes subtype = ((Class<?>) clazz).getAnnotation(JsonSubTypes.class);
        if (subtype != null) {
            int subLevel = level + 1;
            String text = "subtypes:";
            System.err.println(StringUtils.leftPad(text, text.length() + subLevel * 5, "\t-   "));
            for (JsonSubTypes.Type type : subtype.value()) {
                text = "subtype:" + type.name();
                System.err.println(StringUtils.leftPad(text, text.length() + (subLevel + 1) * 5, "\t-   "));
                inspect((subLevel + 1), type.value(), type.name());
            }
        }
    }
}

From source file:objenome.util.bytecode.SgUtils.java

/**
 * Checks if the modifiers are valid for a method. If any of the modifiers
 * is not valid an <code>IllegalArgumentException</code> is thrown.
 * //from  ww  w  .j  a  v a  2 s  . com
 * @param modifiers
 *            Modifiers.
 */
// CHECKSTYLE:OFF Cyclomatic complexity is OK
public static void checkMethodModifiers(int modifiers) {

    // Base check
    checkModifiers(METHOD, modifiers);

    // Check overlapping modifiers
    if (Modifier.isPrivate(modifiers)) {
        if (Modifier.isProtected(modifiers) || Modifier.isPublic(modifiers)) {
            throw new IllegalArgumentException(
                    METHOD_ACCESS_MODIFIER_ERROR + " [" + Modifier.toString(modifiers) + ']');
        }
    }
    if (Modifier.isProtected(modifiers)) {
        if (Modifier.isPrivate(modifiers) || Modifier.isPublic(modifiers)) {
            throw new IllegalArgumentException(
                    METHOD_ACCESS_MODIFIER_ERROR + " [" + Modifier.toString(modifiers) + ']');
        }
    }
    if (Modifier.isPublic(modifiers)) {
        if (Modifier.isPrivate(modifiers) || Modifier.isProtected(modifiers)) {
            throw new IllegalArgumentException(
                    METHOD_ACCESS_MODIFIER_ERROR + " [" + Modifier.toString(modifiers) + ']');
        }
    }

    // Check illegal abstract modifiers
    if (Modifier.isAbstract(modifiers)) {
        if (Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers)
                || Modifier.isNative(modifiers) || Modifier.isStrict(modifiers)
                || Modifier.isSynchronized(modifiers)) {
            throw new IllegalArgumentException(
                    METHOD_ILLEGAL_ABSTRACT_MODIFIERS_ERROR + " [" + Modifier.toString(modifiers) + ']');
        }
    }

    // Check native and strictfp
    if (Modifier.isNative(modifiers) && Modifier.isStrict(modifiers)) {
        throw new IllegalArgumentException(
                METHOD_NATIVE_STRICTFP_ERROR + " [" + Modifier.toString(modifiers) + ']');
    }

}

From source file:com.gwtcx.server.servlet.FileUploadServlet.java

@SuppressWarnings("rawtypes")
private Object createEntity(Class entity, Field[] fields, String[] nextLine) {

    Log.debug("createEntity()");

    try {/*ww  w.  j  a v a  2s . c om*/
        Object object = entity.newInstance();

        for (Field field : fields) {
            Class type = field.getType();

            // ignore Static fields
            if (Modifier.isStatic(field.getModifiers())) {
                continue;
            }

            if (type.getSimpleName().equals("String")) {
                Integer index = fieldNames.get(field.getName());
                if (index != null) {
                    field.set(object, nextLine[index].trim());
                    Log.debug("Field name: " + field.getName() + " index[" + index + "] = " + nextLine[index]);
                }
            } else if (type.getSimpleName().equals("List")) {

                List<Object> list = new ArrayList<Object>();

                Field declaredField = object.getClass().getDeclaredField(field.getName());
                Type genericType = declaredField.getGenericType();

                if (genericType instanceof ParameterizedType) {
                    ParameterizedType pt = (ParameterizedType) genericType;
                    Type[] t = pt.getActualTypeArguments();

                    // e.g. "class au.com.uptick.serendipity.server.domain.Address"
                    String className = t[0].toString().substring(6);
                    Log.debug("className: " + className);

                    Class nestedEntity = Class.forName(className);
                    Field[] nestedFields = nestedEntity.getDeclaredFields();
                    AccessibleObject.setAccessible(nestedFields, true);

                    Object nestedObject = createNestedEntity(nestedEntity, nestedFields, nextLine);

                    if (nestedObject != null) {
                        list.add(nestedObject);
                        field.set(object, list);
                    }
                }
            }
        }

        // Log.debug(object.toString());

        return object;
    } catch (Exception e) {
        Log.error("Error encountered while creating entity", e);
    }

    return null;
}

From source file:jenkins.scm.api.SCMHeadMixinEqualityGenerator.java

/**
 * Creates the {@link SCMHeadMixin.Equality} instance.
 *
 * @param type the {@link SCMHead} type to create the instance for.
 * @return the {@link SCMHeadMixin.Equality} instance.
 *///  w w w  .  j  a va2 s. c o m
@NonNull
private SCMHeadMixin.Equality create(@NonNull Class<? extends SCMHead> type) {
    Map<String, Method> properties = new TreeMap<String, Method>();
    for (Class clazz : (List<Class>) ClassUtils.getAllInterfaces(type)) {
        if (!SCMHeadMixin.class.isAssignableFrom(clazz)) {
            // not a mix-in
            continue;
        }
        if (SCMHeadMixin.class == clazz) {
            // no need to check this by reflection
            continue;
        }
        if (!Modifier.isPublic(clazz.getModifiers())) {
            // not public
            continue;
        }
        // this is a mixin interface, only look at declared properties;
        for (Method method : clazz.getDeclaredMethods()) {
            if (method.getReturnType() == Void.class) {
                // nothing to do with us
                continue;
            }
            if (!Modifier.isPublic(method.getModifiers())) {
                // should never get here
                continue;
            }
            if (Modifier.isStatic(method.getModifiers())) {
                // might get here with Java 8
                continue;
            }
            if (method.getParameterTypes().length != 0) {
                // not a property
                continue;
            }
            String name = method.getName();
            if (!name.matches("^((is[A-Z0-9_].*)|(get[A-Z0-9_].*))$")) {
                // not a property
                continue;
            }
            if (name.startsWith("is")) {
                name = "" + Character.toLowerCase(name.charAt(2))
                        + (name.length() > 3 ? name.substring(3) : "");
            } else {
                name = "" + Character.toLowerCase(name.charAt(3))
                        + (name.length() > 4 ? name.substring(4) : "");
            }
            if (properties.containsKey(name)) {
                // a higher priority interface already defined the method
                continue;
            }
            properties.put(name, method);
        }
    }
    if (properties.isEmpty()) {
        // no properties to consider
        return new ConstantEquality();
    }
    if (forceReflection) {
        return new ReflectiveEquality(properties.values().toArray(new Method[properties.size()]));
    }
    // now we define the class
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
    String name = SCMHeadMixin.class.getPackage().getName() + ".internal." + type.getName();

    // TODO Move to 1.7 opcodes once baseline 1.612+
    cw.visit(Opcodes.V1_6, ACC_PUBLIC, name.replace('.', '/'), null, Type.getInternalName(Object.class),
            new String[] { Type.getInternalName(SCMHeadMixin.Equality.class) });
    generateDefaultConstructor(cw);
    generateEquals(cw, properties.values());
    byte[] image = cw.toByteArray();

    Class<? extends SCMHeadMixin.Equality> c = defineClass(name, image, 0, image.length)
            .asSubclass(SCMHeadMixin.Equality.class);

    try {
        return c.newInstance();
    } catch (InstantiationException e) {
        // fallback to reflection
    } catch (IllegalAccessException e) {
        // fallback to reflection
    }
    return new ReflectiveEquality(properties.values().toArray(new Method[properties.size()]));

}

From source file:net.minecraftforge.common.config.ConfigManager.java

private static void sync(Configuration cfg, Class<?> cls, String modid, String category, boolean loading,
        Object instance) {/*from  w w w  . ja  v  a  2  s .c  om*/
    for (Field f : cls.getDeclaredFields()) {
        if (!Modifier.isPublic(f.getModifiers()))
            continue;

        //Only the root class may have static fields. Otherwise category tree nodes of the same type would share the
        //contained value messing up the sync
        if (Modifier.isStatic(f.getModifiers()) != (instance == null))
            continue;

        if (f.isAnnotationPresent(Config.Ignore.class))
            continue;

        String comment = null;
        Comment ca = f.getAnnotation(Comment.class);
        if (ca != null)
            comment = NEW_LINE.join(ca.value());

        String langKey = modid + "." + (category.isEmpty() ? "" : category + Configuration.CATEGORY_SPLITTER)
                + f.getName().toLowerCase(Locale.ENGLISH);
        LangKey la = f.getAnnotation(LangKey.class);
        if (la != null)
            langKey = la.value();

        boolean requiresMcRestart = f.isAnnotationPresent(Config.RequiresMcRestart.class);
        boolean requiresWorldRestart = f.isAnnotationPresent(Config.RequiresWorldRestart.class);

        if (FieldWrapper.hasWrapperFor(f)) //Wrappers exist for primitives, enums, maps and arrays
        {
            if (Strings.isNullOrEmpty(category))
                throw new RuntimeException(
                        "An empty category may not contain anything but objects representing categories!");
            try {
                IFieldWrapper wrapper = FieldWrapper.get(instance, f, category);
                ITypeAdapter adapt = wrapper.getTypeAdapter();
                Property.Type propType = adapt.getType();

                for (String key : wrapper.getKeys()) //Iterate the fully qualified property names the field provides
                {
                    String suffix = StringUtils.replaceOnce(key,
                            wrapper.getCategory() + Configuration.CATEGORY_SPLITTER, "");

                    boolean existed = exists(cfg, wrapper.getCategory(), suffix);
                    if (!existed || loading) //Creates keys in category specified by the wrapper if new ones are programaticaly added
                    {
                        Property property = property(cfg, wrapper.getCategory(), suffix, propType,
                                adapt.isArrayAdapter());

                        adapt.setDefaultValue(property, wrapper.getValue(key));
                        if (!existed)
                            adapt.setValue(property, wrapper.getValue(key));
                        else
                            wrapper.setValue(key, adapt.getValue(property));
                    } else //If the key is not new, sync according to shouldReadFromVar()
                    {
                        Property property = property(cfg, wrapper.getCategory(), suffix, propType,
                                adapt.isArrayAdapter());
                        Object propVal = adapt.getValue(property);
                        Object mapVal = wrapper.getValue(key);
                        if (shouldReadFromVar(property, propVal, mapVal))
                            adapt.setValue(property, mapVal);
                        else
                            wrapper.setValue(key, propVal);
                    }
                }

                ConfigCategory confCat = cfg.getCategory(wrapper.getCategory());

                for (Property property : confCat.getOrderedValues()) //Iterate the properties to check for new data from the config side
                {
                    String key = confCat.getQualifiedName() + Configuration.CATEGORY_SPLITTER
                            + property.getName();
                    if (!wrapper.handlesKey(key))
                        continue;

                    if (loading || !wrapper.hasKey(key)) {
                        Object value = wrapper.getTypeAdapter().getValue(property);
                        wrapper.setValue(key, value);
                    }
                }

                if (loading)
                    wrapper.setupConfiguration(cfg, comment, langKey, requiresMcRestart, requiresWorldRestart);

            } catch (Exception e) {
                String format = "Error syncing field '%s' of class '%s'!";
                String error = String.format(format, f.getName(), cls.getName());
                throw new RuntimeException(error, e);
            }
        } else if (f.getType().getSuperclass() != null && f.getType().getSuperclass().equals(Object.class)) { //If the field extends Object directly, descend the object tree and access the objects members
            Object newInstance = null;
            try {
                newInstance = f.get(instance);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }

            //Setup the sub category with its respective name, comment, language key, etc.
            String sub = (category.isEmpty() ? "" : category + Configuration.CATEGORY_SPLITTER)
                    + getName(f).toLowerCase(Locale.ENGLISH);
            ConfigCategory confCat = cfg.getCategory(sub);
            confCat.setComment(comment);
            confCat.setLanguageKey(langKey);
            confCat.setRequiresMcRestart(requiresMcRestart);
            confCat.setRequiresWorldRestart(requiresWorldRestart);

            sync(cfg, f.getType(), modid, sub, loading, newInstance);
        } else {
            String format = "Can't handle field '%s' of class '%s': Unknown type.";
            String error = String.format(format, f.getName(), cls.getCanonicalName());
            throw new RuntimeException(error);
        }
    }
}

From source file:org.apache.camel.maven.JavadocApiMethodGeneratorMojo.java

private String getResultType(Class<?> aClass, String name, String[] types) throws MojoExecutionException {
    Class<?>[] argTypes = new Class<?>[types.length];
    final ClassLoader classLoader = getProjectClassLoader();
    for (int i = 0; i < types.length; i++) {
        try {// w  w  w .j a  va2 s  .c o  m
            try {
                argTypes[i] = ApiMethodParser.forName(types[i], classLoader);
            } catch (ClassNotFoundException e) {
                throw new MojoExecutionException(e.getMessage(), e);
            }
        } catch (IllegalArgumentException e) {
            throw new MojoExecutionException(e.getCause().getMessage(), e.getCause());
        }
    }

    // return null for non-public methods, and for non-static methods if includeStaticMethods is null or false
    String result = null;
    try {
        final Method method = aClass.getMethod(name, argTypes);
        int modifiers = method.getModifiers();
        if (!Modifier.isStatic(modifiers) || Boolean.TRUE.equals(includeStaticMethods)) {
            result = method.getReturnType().getCanonicalName();
        }
    } catch (NoSuchMethodException e) {
        // could be a non-public method
        try {
            aClass.getDeclaredMethod(name, argTypes);
        } catch (NoSuchMethodException e1) {
            throw new MojoExecutionException(e1.getMessage(), e1);
        }
    }

    return result;
}

From source file:com.baidu.jprotobuf.pbrpc.spring.annotation.CommonAnnotationBeanPostProcessor.java

private InjectionMetadata findAnnotationMetadata(final Class clazz,
        final List<Class<? extends Annotation>> annotion) {
    // Quick check on the concurrent map first, with minimal locking.
    InjectionMetadata metadata = this.injectionMetadataCache.get(clazz);
    if (metadata == null) {
        synchronized (this.injectionMetadataCache) {
            metadata = this.injectionMetadataCache.get(clazz);
            if (metadata == null) {
                final InjectionMetadata newMetadata = new InjectionMetadata(clazz);
                ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() {
                    public void doWith(Field field) {
                        for (Class<? extends Annotation> anno : annotion) {
                            Annotation annotation = field.getAnnotation(anno);
                            if (annotation != null) {
                                if (Modifier.isStatic(field.getModifiers())) {
                                    throw new IllegalStateException(
                                            "Autowired annotation is not supported on static fields");
                                }//from w  w  w  .ja  v  a2 s . c  o m
                                newMetadata.addInjectedField(new AutowiredFieldElement(field, annotation));
                            }

                        }
                    }
                });
                ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() {
                    public void doWith(Method method) {
                        for (Class<? extends Annotation> anno : annotion) {
                            Annotation annotation = method.getAnnotation(anno);
                            if (annotation != null
                                    && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                                if (Modifier.isStatic(method.getModifiers())) {
                                    throw new IllegalStateException(
                                            "Autowired annotation is not supported on static methods");
                                }
                                if (method.getParameterTypes().length == 0) {
                                    throw new IllegalStateException(
                                            "Autowired annotation requires at least one argument: " + method);
                                }
                                PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
                                newMetadata
                                        .addInjectedMethod(new AutowiredMethodElement(method, annotation, pd));
                            }

                        }
                    }
                });
                metadata = newMetadata;
                this.injectionMetadataCache.put(clazz, metadata);
            }
        }
    }
    return metadata;
}

From source file:org.apache.hadoop.hive.metastore.VerifyingObjectStore.java

private static void dumpObject(StringBuilder errorStr, String name, Object p, Class<?> c, int level)
        throws IllegalAccessException {
    String offsetStr = repeat("  ", level);
    if (p == null || c == String.class || c.isPrimitive() || ClassUtils.wrapperToPrimitive(c) != null) {
        errorStr.append(offsetStr).append(name + ": [" + p + "]\n");
    } else if (ClassUtils.isAssignable(c, Iterable.class)) {
        errorStr.append(offsetStr).append(name + " is an iterable\n");
        Iterator<?> i1 = ((Iterable<?>) p).iterator();
        int i = 0;
        while (i1.hasNext()) {
            Object o1 = i1.next();
            Class<?> t = o1 == null ? Object.class : o1.getClass(); // ...
            dumpObject(errorStr, name + "[" + (i++) + "]", o1, t, level + 1);
        }//from   ww  w  .  j a va  2s.c  om
    } else if (c.isArray()) {
        int len = Array.getLength(p);
        Class<?> t = c.getComponentType();
        errorStr.append(offsetStr).append(name + " is an array\n");
        for (int i = 0; i < len; ++i) {
            dumpObject(errorStr, name + "[" + i + "]", Array.get(p, i), t, level + 1);
        }
    } else if (ClassUtils.isAssignable(c, Map.class)) {
        Map<?, ?> c1 = (Map<?, ?>) p;
        errorStr.append(offsetStr).append(name + " is a map\n");
        dumpObject(errorStr, name + ".keys", c1.keySet(), Set.class, level + 1);
        dumpObject(errorStr, name + ".vals", c1.values(), Collection.class, level + 1);
    } else {
        errorStr.append(offsetStr).append(name + " is of type " + c.getCanonicalName() + "\n");
        // TODO: this doesn't include superclass.
        Field[] fields = c.getDeclaredFields();
        AccessibleObject.setAccessible(fields, true);
        for (int i = 0; i < fields.length; i++) {
            Field f = fields[i];
            if (f.getName().indexOf('$') != -1 || Modifier.isStatic(f.getModifiers()))
                continue;
            dumpObject(errorStr, name + "." + f.getName(), f.get(p), f.getType(), level + 1);
        }
    }
}