package railo.runtime.dump; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.sql.ResultSet; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Locale; import java.util.Map; import java.util.Set; import javax.servlet.http.Cookie; import javax.servlet.http.HttpSession; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import railo.commons.date.TimeZoneUtil; import railo.commons.io.res.Resource; import railo.commons.lang.IDGenerator; import railo.commons.lang.StringUtil; import railo.runtime.PageContext; import railo.runtime.coder.Base64Coder; import railo.runtime.converter.WDDXConverter; import railo.runtime.exp.PageException; import railo.runtime.op.Caster; import railo.runtime.op.Decision; import railo.runtime.text.xml.XMLCaster; import railo.runtime.type.Array; import railo.runtime.type.Collection; import railo.runtime.type.ObjectWrap; import railo.runtime.type.QueryImpl; import railo.runtime.type.dt.DateTimeImpl; import railo.runtime.type.scope.CookieImpl; public class DumpUtil { public static final DumpData MAX_LEVEL_REACHED; static { MAX_LEVEL_REACHED = new DumpTable("Max Level Reached","#e0e0e0","#ffcc99","#888888"); ((DumpTable)MAX_LEVEL_REACHED).appendRow( new DumpRow(1, new SimpleDumpData("[Max Dump Level Reached]") ) ); } public static DumpData toDumpData(Object o, PageContext pageContext, int maxlevel, DumpProperties props) { if(maxlevel<0) return MAX_LEVEL_REACHED; // null if(o == null) { DumpTable table=new DumpTable("null","#ff6600","#ffcc99","#000000"); table.appendRow(new DumpRow(0,new SimpleDumpData("Empty:null"))); return table; } if(o instanceof DumpData) { return ((DumpData)o); } // Date if(o instanceof Date) { return new DateTimeImpl((Date) o).toDumpData(pageContext,maxlevel,props); } // Calendar if(o instanceof Calendar) { Calendar c=(Calendar)o; SimpleDateFormat df = new SimpleDateFormat("EE, dd MMM yyyy HH:mm:ss zz",Locale.ENGLISH); df.setTimeZone(c.getTimeZone()); DumpTable table=new DumpTable("date","#ff9900","#ffcc00","#000000"); table.setTitle("java.util.Calendar"); table.appendRow(1, new SimpleDumpData("Timezone"), new SimpleDumpData(TimeZoneUtil.toString(c.getTimeZone()))); table.appendRow(1, new SimpleDumpData("Time"), new SimpleDumpData(df.format(c.getTime()))); return table; } // StringBuffer if(o instanceof StringBuffer) { DumpTable dt=(DumpTable)toDumpData(o.toString(), pageContext, maxlevel, props); if(StringUtil.isEmpty(dt.getTitle())) dt.setTitle(Caster.toClassName(o)); return dt; } // StringBuilder if(o instanceof StringBuilder) { DumpTable dt=(DumpTable)toDumpData(o.toString(), pageContext, maxlevel, props); if(StringUtil.isEmpty(dt.getTitle())) dt.setTitle(Caster.toClassName(o)); return dt; } // String if(o instanceof String) { String str=(String) o; if(str.trim().startsWith("<wddxPacket ")) { try { WDDXConverter converter =new WDDXConverter(pageContext.getTimeZone(),false,true); converter.setTimeZone(pageContext.getTimeZone()); Object rst = converter.deserialize(str,false); DumpData data = toDumpData(rst, pageContext, maxlevel, props); DumpTable table = new DumpTable("string","#cc9999","#ffffff","#000000"); table.setTitle("WDDX"); table.appendRow(1,new SimpleDumpData("encoded"),data); table.appendRow(1,new SimpleDumpData("raw"),new SimpleDumpData(str)); return table; } catch(Throwable t) {} } DumpTable table = new DumpTable("string","#ff6600","#ffcc99","#000000"); table.appendRow(1,new SimpleDumpData("string"),new SimpleDumpData(str)); return table; } // Character if(o instanceof Character) { DumpTable table = new DumpTable("character","#ff6600","#ffcc99","#000000"); table.appendRow(1,new SimpleDumpData("character"),new SimpleDumpData(o.toString())); return table; } // Number if(o instanceof Number) { DumpTable table = new DumpTable("numeric","#ff6600","#ffcc99","#000000"); table.appendRow(1,new SimpleDumpData("number"),new SimpleDumpData(Caster.toString(((Number)o)))); return table; } // Boolean if(o instanceof Boolean) { DumpTable table = new DumpTable("boolean","#ff6600","#ffcc99","#000000"); table.appendRow(1,new SimpleDumpData("boolean"),new SimpleDumpData(((Boolean)o).booleanValue())); return table; } // File if(o instanceof File) { DumpTable table = new DumpTable("file","#ffcc00","#ffff66","#000000"); table.appendRow(1,new SimpleDumpData("File"),new SimpleDumpData(o.toString())); return table; } // Cookie if(o instanceof Cookie) { Cookie c=(Cookie) o; DumpTable table = new DumpTable("Cookie","#979EAA","#DEE9FB","#000000"); table.setTitle("Cookie ("+c.getClass().getName()+")"); table.appendRow(1,new SimpleDumpData("name"),new SimpleDumpData(c.getName())); table.appendRow(1,new SimpleDumpData("value"),new SimpleDumpData(c.getValue())); table.appendRow(1,new SimpleDumpData("path"),new SimpleDumpData(c.getPath())); table.appendRow(1,new SimpleDumpData("secure"),new SimpleDumpData(c.getSecure())); table.appendRow(1,new SimpleDumpData("maxAge"),new SimpleDumpData(c.getMaxAge())); table.appendRow(1,new SimpleDumpData("version"),new SimpleDumpData(c.getVersion())); table.appendRow(1,new SimpleDumpData("domain"),new SimpleDumpData(c.getDomain())); table.appendRow(1,new SimpleDumpData("httpOnly"),new SimpleDumpData(CookieImpl.isHTTPOnly(c))); table.appendRow(1,new SimpleDumpData("comment"),new SimpleDumpData(c.getComment())); return table; } // Resource if(o instanceof Resource) { DumpTable table = new DumpTable("resource","#ffcc00","#ffff66","#000000"); table.appendRow(1,new SimpleDumpData("Resource"),new SimpleDumpData(o.toString())); return table; } // byte[] if(o instanceof byte[]) { byte[] bytes=(byte[]) o; int max=5000; DumpTable table = new DumpTable("array","#ff9900","#ffcc00","#000000"); table.setTitle("Native Array ("+Caster.toClassName(o)+")"); StringBuilder sb=new StringBuilder("["); for(int i=0;i<bytes.length;i++) { if(i!=0)sb.append(","); sb.append(bytes[i]); if(i==max) { sb.append(", ...truncated"); break; } } sb.append("]"); table.appendRow(1,new SimpleDumpData("Raw"+(bytes.length<max?"":" (truncated)")),new SimpleDumpData(sb.toString())); if(bytes.length<max) { // base64 table.appendRow(1,new SimpleDumpData("Base64 Encoded"),new SimpleDumpData(Base64Coder.encode(bytes))); /*try { table.appendRow(1,new SimpleDumpData("CFML expression"),new SimpleDumpData("evaluateJava('"+JavaConverter.serialize(bytes)+"')")); } catch (IOException e) {}*/ } return table; } // Collection.Key if(o instanceof Collection.Key) { Collection.Key key=(Collection.Key) o; DumpTable table = new DumpTable("string","#ff6600","#ffcc99","#000000"); table.appendRow(1,new SimpleDumpData("Collection.Key"),new SimpleDumpData(key.getString())); return table; } String id=""+IDGenerator.intId(); String refid=ThreadLocalDump.get(o); if(refid!=null) { DumpTable table = new DumpTable("ref","#ffffff","#cccccc","#000000"); table.appendRow(1,new SimpleDumpData("Reference"),new SimpleDumpData(refid)); table.setRef(refid); return setId(id,table); } ThreadLocalDump.set(o,id); try{ int top = props.getMaxlevel(); // Printable if(o instanceof Dumpable) { return setId(id,((Dumpable)o).toDumpData(pageContext,maxlevel,props)); } // Map if(o instanceof Map) { Map map=(Map) o; Iterator it=map.keySet().iterator(); DumpTable table = new DumpTable("struct","#ff9900","#ffcc00","#000000"); table.setTitle("Map ("+Caster.toClassName(o)+")"); while(it.hasNext()) { Object next=it.next(); table.appendRow(1,toDumpData(next,pageContext,maxlevel,props),toDumpData(map.get(next),pageContext,maxlevel,props)); } return setId(id,table); } // List if(o instanceof List) { List list=(List) o; ListIterator it=list.listIterator(); DumpTable table = new DumpTable("array","#ff9900","#ffcc00","#000000"); table.setTitle("Array (List)"); if ( list.size() > top ) table.setComment("Rows: " + list.size() + " (showing top " + top + ")"); int i = 0; while(it.hasNext() && i++ < top) { table.appendRow(1,new SimpleDumpData(it.nextIndex()+1),toDumpData(it.next(),pageContext,maxlevel,props)); } return setId(id,table); } // Set if(o instanceof Set) { Set set=(Set) o; Iterator it = set.iterator(); DumpTable table = new DumpTable("array","#ff9900","#ffcc00","#000000"); table.setTitle("Set ("+set.getClass().getName()+")"); int i = 0; while(it.hasNext() && i++ < top) { table.appendRow(1,toDumpData(it.next(),pageContext,maxlevel,props)); } return setId(id,table); } // Resultset if(o instanceof ResultSet) { try { DumpData dd = new QueryImpl((ResultSet)o,"query",pageContext.getTimeZone()).toDumpData(pageContext,maxlevel,props); if(dd instanceof DumpTable) ((DumpTable)dd).setTitle(Caster.toClassName(o)); return setId(id,dd); } catch (PageException e) { } } // Enumeration if(o instanceof Enumeration) { Enumeration e=(Enumeration)o; DumpTable table = new DumpTable("enumeration","#ff9900","#ffcc00","#000000"); table.setTitle("Enumeration"); int i = 0; while(e.hasMoreElements() && i++ < top) { table.appendRow(0,toDumpData(e.nextElement(),pageContext,maxlevel,props)); } return setId(id,table); } // Object[] if(Decision.isNativeArray(o)) { Array arr; try { arr = Caster.toArray(o); DumpTable htmlBox = new DumpTable("array","#ff9900","#ffcc00","#000000"); htmlBox.setTitle("Native Array ("+Caster.toClassName(o)+")"); int length=arr.size(); for(int i=1;i<=length;i++) { Object ox=null; try { ox = arr.getE(i); } catch (Exception e) {} htmlBox.appendRow(1,new SimpleDumpData(i),toDumpData(ox,pageContext,maxlevel,props)); } return setId(id,htmlBox); } catch (PageException e) { return setId(id,new SimpleDumpData("")); } } // Node if(o instanceof Node) { return setId(id,XMLCaster.toDumpData((Node)o, pageContext,maxlevel,props)); } // ObjectWrap if(o instanceof ObjectWrap) { maxlevel++; return setId(id,toDumpData(((ObjectWrap)o).getEmbededObject(null), pageContext,maxlevel,props)); } // NodeList if(o instanceof NodeList) { NodeList list=(NodeList)o; int len=list.getLength(); DumpTable table = new DumpTable("xml","#cc9999","#ffffff","#000000"); for(int i=0;i<len;i++) { table.appendRow(1,new SimpleDumpData(i),toDumpData(list.item(i),pageContext,maxlevel,props)); } return setId(id,table); } // AttributeMap if(o instanceof NamedNodeMap) { NamedNodeMap attr = (NamedNodeMap)o; int len = attr.getLength(); DumpTable dt = new DumpTable("array","#ff9900","#ffcc00","#000000"); dt.setTitle("NamedNodeMap ("+Caster.toClassName(o)+")"); for(int i=0;i<len;i++) { dt.appendRow(1,new SimpleDumpData(i),toDumpData(attr.item(i),pageContext,maxlevel,props)); } return setId(id,dt); } // HttpSession if(o instanceof HttpSession) { HttpSession hs = (HttpSession)o; Enumeration e = hs.getAttributeNames(); DumpTable htmlBox = new DumpTable("httpsession","#9999ff","#ccccff","#000000"); htmlBox.setTitle("HttpSession"); while(e.hasMoreElements()) { String key=e.nextElement().toString(); htmlBox.appendRow(1,new SimpleDumpData(key),toDumpData(hs.getAttribute(key), pageContext,maxlevel,props)); } return setId(id,htmlBox); } // reflect //else { DumpTable table = new DumpTable(o.getClass().getName(),"#cc9999","#ffcccc","#000000"); Class clazz=o.getClass(); if(o instanceof Class) clazz=(Class) o; String fullClassName=clazz.getName(); int pos=fullClassName.lastIndexOf('.'); String className=pos==-1?fullClassName:fullClassName.substring(pos+1); table.setTitle(className); table.appendRow(1,new SimpleDumpData("class"),new SimpleDumpData(fullClassName)); // Fields Field[] fields=clazz.getFields(); DumpTable fieldDump = new DumpTable("#cc9999","#ffcccc","#000000"); fieldDump.appendRow(7,new SimpleDumpData("name"),new SimpleDumpData("pattern"),new SimpleDumpData("value")); for(int i=0;i<fields.length;i++) { Field field = fields[i]; DumpData value; try {//print.out(o+":"+maxlevel); value=new SimpleDumpData(Caster.toString(field.get(o), "")); } catch (Exception e) { value=new SimpleDumpData(""); } fieldDump.appendRow(0,new SimpleDumpData(field.getName()),new SimpleDumpData(field.toString()),value); } if(fields.length>0)table.appendRow(1,new SimpleDumpData("fields"),fieldDump); // Methods StringBuffer objMethods=new StringBuffer(); Method[] methods=clazz.getMethods(); DumpTable methDump = new DumpTable("#cc9999","#ffcccc","#000000"); methDump.appendRow(7,new SimpleDumpData("return"),new SimpleDumpData("interface"),new SimpleDumpData("exceptions")); for(int i=0;i<methods.length;i++) { Method method = methods[i]; if(Object.class==method.getDeclaringClass()) { if(objMethods.length()>0)objMethods.append(", "); objMethods.append(method.getName()); continue; } // exceptions StringBuffer sbExp=new StringBuffer(); Class[] exceptions = method.getExceptionTypes(); for(int p=0;p<exceptions.length;p++){ if(p>0)sbExp.append("\n"); sbExp.append(Caster.toClassName(exceptions[p])); } // parameters StringBuffer sbParams=new StringBuffer(method.getName()); sbParams.append('('); Class[] parameters = method.getParameterTypes(); for(int p=0;p<parameters.length;p++){ if(p>0)sbParams.append(", "); sbParams.append(Caster.toClassName(parameters[p])); } sbParams.append(')'); methDump.appendRow(0, new SimpleDumpData(Caster.toClassName(method.getReturnType())), new SimpleDumpData(sbParams.toString()), new SimpleDumpData(sbExp.toString()) ); } if(methods.length>0)table.appendRow(1,new SimpleDumpData("methods"),methDump); DumpTable inherited = new DumpTable("#cc9999","#ffcccc","#000000"); inherited.appendRow(7,new SimpleDumpData("Methods inherited from java.lang.Object")); inherited.appendRow(0,new SimpleDumpData(objMethods.toString())); table.appendRow(1,new SimpleDumpData(""),inherited); return setId(id,table); //} } finally{ ThreadLocalDump.remove(o); } } private static DumpData setId(String id, DumpData data) { if(data instanceof DumpTable) { ((DumpTable)data).setId(id); } // TODO Auto-generated method stub return data; } public static boolean keyValid(DumpProperties props,int level, String key) { if(props.getMaxlevel()-level>1) return true; // show Set set = props.getShow(); if(set!=null && !set.contains(StringUtil.toLowerCase(key))) return false; // hide set = props.getHide(); if(set!=null && set.contains(StringUtil.toLowerCase(key))) return false; return true; } public static boolean keyValid(DumpProperties props,int level, Collection.Key key) { if(props.getMaxlevel()-level>1) return true; // show Set set = props.getShow(); if(set!=null && !set.contains(key.getLowerString())) return false; // hide set = props.getHide(); if(set!=null && set.contains(key.getLowerString())) return false; return true; } public static DumpProperties toDumpProperties() { return DumpProperties.DEFAULT; } }