/* * Created on Oct 13, 2003 * * Works with beans that have private members, arrays, collections, ... whatever. * * @author Pinkham */ import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.Iterator; import java.util.List; /** * Get a debug string from any bean. Handles arrays and Collections. * Does NOT detect reference cycles (stack will overflow). */ public final class DebugPrint { private DebugPrint() {} // setter methods below let you change these to suit your style private static String beanPrefix = ":{"; private static String beanSuffix = "}"; private static String valueSeparator = "="; private static String nullStr = "null"; private static String elementSeparator = "\n"; private static String propertySeparator = "\n"; // try ";" or "," for brevity /** * Given a JavaBean (an object with getter methods) this method will * find and call the getter methods and prepare a toString * that lists the values of all it's properties. The format looks like this: * * package.BeanName:{prop=value\nprop2=value2} * */ public static String toString(Object bean) { if (bean == null) return nullStr; // Put classes that need special handling here... if (bean instanceof java.util.Calendar) return ((java.util.Calendar)bean).getTime().toString(); Class c = bean.getClass(); if (isLeafClass(c)) return bean.toString(); // bean must be just a primitive type BeanInfo bi; try { bi = Introspector.getBeanInfo(c, Object.class); // don't want Object methods like getClass } catch (IntrospectionException e) { bi = null; } PropertyDescriptor[] pd = null; if (bi != null) pd = bi.getPropertyDescriptors(); if (pd == null || pd.length==0) // no properties return bean.toString(); String ret = c.getName()+beanPrefix; for (int i=0; i0) ret += propertySeparator; //ret += pd[i].getName() + valueSeparator; Method getter = pd[i].getReadMethod(); if (getter == null) // skip props with setter only continue; Object value; try { value = getter.invoke(bean, new Object[0]); } catch (Exception e) // invokationTarget, illegalArgument, illegalAccess { value = e.toString(); } if (getter.getReturnType().isArray()) { if (value == null) { ret += pd[i].getName() + "[]" + valueSeparator + nullStr; } else { Object[] values = (Object[]) value; for (int j=0; j0) ret += elementSeparator; ret += pd[i].getName() + "[" + j + "]" + valueSeparator + toString(values[j]); } } } else { if (value instanceof Collection) { Iterator k = ((Collection)value).iterator(); int j=0; boolean first = true; while (k.hasNext()) { if (first) { first = false; ret += elementSeparator; } ret += pd[i].getName() + "[" + j + "]" + valueSeparator + toString(k.next()); } } else { ret += pd[i].getName() + valueSeparator + toString(value); } } } ret += beanSuffix; return ret; } // stop recursion and just do toString for these classes private static List LEAF_CLASSES = null; private static boolean isLeafClass(Class c) { if (LEAF_CLASSES == null) { LEAF_CLASSES = new ArrayList(); LEAF_CLASSES.add(String.class); LEAF_CLASSES.add(Date.class); LEAF_CLASSES.add(Float.class); LEAF_CLASSES.add(Double.class); LEAF_CLASSES.add(Integer.class); LEAF_CLASSES.add(Long.class); } return LEAF_CLASSES.contains(c); } // modify as needed to format toString result public static void setBeanPrefix(String beanPrefix) { DebugPrint.beanPrefix = beanPrefix; } public static void setBeanSuffix(String beanSuffix) { DebugPrint.beanSuffix = beanSuffix; } public static void setValueSeparator(String valueSeparator) { DebugPrint.valueSeparator = valueSeparator; } public static void setNullStr(String nullStr) { DebugPrint.nullStr = nullStr; } public static void setArrayElementSeparator(String arrayElementSeparator) { DebugPrint.elementSeparator = arrayElementSeparator; } public static void setElementSeparator(String elementSeparator) { DebugPrint.elementSeparator = elementSeparator; } public static void setPropertySeparator(String propertySeparator) { DebugPrint.propertySeparator = propertySeparator; } }