001 package railo.runtime.dump; 002 003 import java.io.File; 004 import java.lang.reflect.Field; 005 import java.lang.reflect.Method; 006 import java.sql.ResultSet; 007 import java.text.SimpleDateFormat; 008 import java.util.Calendar; 009 import java.util.Date; 010 import java.util.Enumeration; 011 import java.util.Iterator; 012 import java.util.List; 013 import java.util.ListIterator; 014 import java.util.Locale; 015 import java.util.Map; 016 import java.util.Set; 017 018 import javax.servlet.http.Cookie; 019 import javax.servlet.http.HttpSession; 020 021 import org.apache.xerces.dom.AttributeMap; 022 import org.w3c.dom.Node; 023 import org.w3c.dom.NodeList; 024 025 import railo.commons.date.TimeZoneUtil; 026 import railo.commons.io.res.Resource; 027 import railo.commons.lang.IDGenerator; 028 import railo.commons.lang.StringUtil; 029 import railo.runtime.PageContext; 030 import railo.runtime.converter.WDDXConverter; 031 import railo.runtime.exp.PageException; 032 import railo.runtime.op.Caster; 033 import railo.runtime.op.Decision; 034 import railo.runtime.text.xml.XMLAttributes; 035 import railo.runtime.text.xml.XMLCaster; 036 import railo.runtime.type.Array; 037 import railo.runtime.type.Collection; 038 import railo.runtime.type.ObjectWrap; 039 import railo.runtime.type.QueryImpl; 040 import railo.runtime.type.dt.DateTimeImpl; 041 042 public class DumpUtil { 043 044 045 public static DumpData toDumpData(Object o,PageContext pageContext, int maxlevel, DumpProperties props) { 046 if(maxlevel<=0) { 047 return new SimpleDumpData("maximal dump level reached"); 048 } 049 // null 050 if(o == null) { 051 DumpTable table=new DumpTablePro("null","#ff6600","#ffcc99","#000000"); 052 table.appendRow(new DumpRow(0,new SimpleDumpData("Empty:null"))); 053 return table; 054 } 055 if(o instanceof DumpData) { 056 return ((DumpData)o); 057 } 058 // Date 059 if(o instanceof Date) { 060 return new DateTimeImpl((Date) o).toDumpData(pageContext,maxlevel,props); 061 } 062 // Calendar 063 if(o instanceof Calendar) { 064 Calendar c=(Calendar)o; 065 066 SimpleDateFormat df = new SimpleDateFormat("EE, dd MMM yyyy HH:mm:ss zz",Locale.ENGLISH); 067 df.setTimeZone(c.getTimeZone()); 068 069 DumpTable table=new DumpTablePro("date","#ff9900","#ffcc00","#000000"); 070 table.setTitle("java.util.Calendar"); 071 table.appendRow(1, new SimpleDumpData("Timezone"), new SimpleDumpData(TimeZoneUtil.toString(c.getTimeZone()))); 072 table.appendRow(1, new SimpleDumpData("Time"), new SimpleDumpData(df.format(c.getTime()))); 073 074 return table; 075 } 076 // StringBuffer 077 if(o instanceof StringBuffer) { 078 DumpTable dt=(DumpTable)toDumpData(o.toString(), pageContext, maxlevel, props); 079 if(StringUtil.isEmpty(dt.getTitle())) 080 dt.setTitle(Caster.toClassName(o)); 081 return dt; 082 } 083 // StringBuilder 084 if(o instanceof StringBuilder) { 085 DumpTable dt=(DumpTable)toDumpData(o.toString(), pageContext, maxlevel, props); 086 if(StringUtil.isEmpty(dt.getTitle())) 087 dt.setTitle(Caster.toClassName(o)); 088 return dt; 089 } 090 // String 091 if(o instanceof String) { 092 String str=(String) o; 093 if(str.trim().startsWith("<wddxPacket ")) { 094 try { 095 WDDXConverter converter =new WDDXConverter(pageContext.getTimeZone(),false,true); 096 converter.setTimeZone(pageContext.getTimeZone()); 097 Object rst = converter.deserialize(str,false); 098 DumpData data = toDumpData(rst, pageContext, maxlevel, props); 099 100 DumpTable table = new DumpTablePro("string","#cc9999","#ffffff","#000000"); 101 table.setTitle("WDDX"); 102 table.appendRow(1,new SimpleDumpData("encoded"),data); 103 table.appendRow(1,new SimpleDumpData("raw"),new SimpleDumpData(str)); 104 return table; 105 } 106 catch(Throwable t) {} 107 } 108 DumpTable table = new DumpTablePro("string","#ff6600","#ffcc99","#000000"); 109 table.appendRow(1,new SimpleDumpData("string"),new SimpleDumpData(str)); 110 return table; 111 } 112 // Character 113 if(o instanceof Character) { 114 DumpTable table = new DumpTablePro("character","#ff6600","#ffcc99","#000000"); 115 table.appendRow(1,new SimpleDumpData("character"),new SimpleDumpData(o.toString())); 116 return table; 117 } 118 // Number 119 if(o instanceof Number) { 120 DumpTable table = new DumpTablePro("numeric","#ff6600","#ffcc99","#000000"); 121 table.appendRow(1,new SimpleDumpData("number"),new SimpleDumpData(Caster.toString(((Number)o).doubleValue()))); 122 return table; 123 } 124 // Boolean 125 if(o instanceof Boolean) { 126 DumpTable table = new DumpTablePro("boolean","#ff6600","#ffcc99","#000000"); 127 table.appendRow(1,new SimpleDumpData("boolean"),new SimpleDumpData(((Boolean)o).booleanValue())); 128 return table; 129 } 130 // File 131 if(o instanceof File) { 132 DumpTable table = new DumpTablePro("file","#ffcc00","#ffff66","#000000"); 133 table.appendRow(1,new SimpleDumpData("File"),new SimpleDumpData(o.toString())); 134 return table; 135 } 136 // Cookie 137 if(o instanceof Cookie) { 138 Cookie c=(Cookie) o; 139 DumpTable table = new DumpTablePro("Cookie","#979EAA","#DEE9FB","#000000"); 140 table.setTitle("Cookie ("+c.getClass().getName()+")"); 141 table.appendRow(1,new SimpleDumpData("name"),new SimpleDumpData(c.getName())); 142 table.appendRow(1,new SimpleDumpData("value"),new SimpleDumpData(c.getValue())); 143 table.appendRow(1,new SimpleDumpData("path"),new SimpleDumpData(c.getPath())); 144 table.appendRow(1,new SimpleDumpData("secure"),new SimpleDumpData(c.getSecure())); 145 table.appendRow(1,new SimpleDumpData("maxAge"),new SimpleDumpData(c.getMaxAge())); 146 table.appendRow(1,new SimpleDumpData("version"),new SimpleDumpData(c.getVersion())); 147 table.appendRow(1,new SimpleDumpData("domain"),new SimpleDumpData(c.getDomain())); 148 table.appendRow(1,new SimpleDumpData("comment"),new SimpleDumpData(c.getComment())); 149 return table; 150 } 151 // Resource 152 if(o instanceof Resource) { 153 DumpTable table = new DumpTablePro("resource","#ffcc00","#ffff66","#000000"); 154 table.appendRow(1,new SimpleDumpData("Resource"),new SimpleDumpData(o.toString())); 155 return table; 156 } 157 // byte[] 158 if(o instanceof byte[]) { 159 byte[] bytes=(byte[]) o; 160 161 DumpTable table = new DumpTablePro("array","#ff9900","#ffcc00","#000000"); 162 table.setTitle("Native Array ("+Caster.toClassName(o)+")"); 163 164 StringBuffer sb=new StringBuffer(); 165 for(int i=0;i<bytes.length;i++) { 166 if(i!=0)sb.append("-"); 167 sb.append(bytes[i]); 168 if(i==1000) { 169 sb.append(" [truncated] "); 170 break; 171 } 172 } 173 table.appendRow(0,new SimpleDumpData(sb.toString())); 174 return table; 175 } 176 // Collection.Key 177 if(o instanceof Collection.Key) { 178 Collection.Key key=(Collection.Key) o; 179 DumpTable table = new DumpTablePro("string","#ff6600","#ffcc99","#000000"); 180 table.appendRow(1,new SimpleDumpData("Collection.Key"),new SimpleDumpData(key.getString())); 181 return table; 182 } 183 184 185 String id=""+IDGenerator.intId(); 186 String refid=ThreadLocalDump.get(o); 187 if(refid!=null) { 188 DumpTablePro table = new DumpTablePro("ref","#ffffff","#cccccc","#000000"); 189 table.appendRow(1,new SimpleDumpData("Reference"),new SimpleDumpData(refid)); 190 table.setRef(refid); 191 return setId(id,table); 192 } 193 194 ThreadLocalDump.set(o,id); 195 try{ 196 // Printable 197 if(o instanceof Dumpable) { 198 return setId(id,((Dumpable)o).toDumpData(pageContext,maxlevel,props)); 199 } 200 // Map 201 if(o instanceof Map) { 202 Map map=(Map) o; 203 Iterator it=map.keySet().iterator(); 204 205 DumpTable table = new DumpTablePro("struct","#ff9900","#ffcc00","#000000"); 206 table.setTitle("Map ("+Caster.toClassName(o)+")"); 207 208 while(it.hasNext()) { 209 Object next=it.next(); 210 table.appendRow(1,toDumpData(next,pageContext,maxlevel,props),toDumpData(map.get(next),pageContext,maxlevel,props)); 211 } 212 return setId(id,table); 213 } 214 215 // List 216 if(o instanceof List) { 217 List list=(List) o; 218 ListIterator it=list.listIterator(); 219 220 DumpTable table = new DumpTablePro("array","#ff9900","#ffcc00","#000000"); 221 table.setTitle("Array (List)"); 222 223 while(it.hasNext()) { 224 table.appendRow(1,new SimpleDumpData(it.nextIndex()+1),toDumpData(it.next(),pageContext,maxlevel,props)); 225 } 226 return setId(id,table); 227 } 228 // Resultset 229 if(o instanceof ResultSet) { 230 try { 231 DumpData dd = new QueryImpl((ResultSet)o,"query").toDumpData(pageContext,maxlevel,props); 232 if(dd instanceof DumpTable) 233 ((DumpTable)dd).setTitle(Caster.toClassName(o)); 234 return setId(id,dd); 235 } 236 catch (PageException e) { 237 238 } 239 } 240 // Enumeration 241 if(o instanceof Enumeration) { 242 Enumeration e=(Enumeration)o; 243 244 DumpTable table = new DumpTablePro("enumeration","#ff9900","#ffcc00","#000000"); 245 table.setTitle("Enumeration"); 246 247 while(e.hasMoreElements()) { 248 table.appendRow(0,toDumpData(e.nextElement(),pageContext,maxlevel,props)); 249 } 250 return setId(id,table); 251 } 252 // Object[] 253 if(Decision.isNativeArray(o)) { 254 Array arr; 255 try { 256 arr = Caster.toArray(o); 257 DumpTable htmlBox = new DumpTablePro("array","#ff9900","#ffcc00","#000000"); 258 htmlBox.setTitle("Native Array ("+Caster.toClassName(o)+")"); 259 260 int length=arr.size(); 261 262 for(int i=1;i<=length;i++) { 263 Object ox=null; 264 try { 265 ox = arr.getE(i); 266 } catch (Exception e) {} 267 htmlBox.appendRow(1,new SimpleDumpData(i),toDumpData(ox,pageContext,maxlevel,props)); 268 } 269 return setId(id,htmlBox); 270 } 271 catch (PageException e) { 272 return setId(id,new SimpleDumpData("")); 273 } 274 } 275 // Node 276 if(o instanceof Node) { 277 return setId(id,XMLCaster.toDumpData((Node)o, pageContext,maxlevel,props)); 278 } 279 // ObjectWrap 280 if(o instanceof ObjectWrap) { 281 maxlevel++; 282 return setId(id,toDumpData(((ObjectWrap)o).getEmbededObject(null), pageContext,maxlevel,props)); 283 } 284 // NodeList 285 if(o instanceof NodeList) { 286 NodeList list=(NodeList)o; 287 int len=list.getLength(); 288 DumpTable table = new DumpTablePro("xml","#cc9999","#ffffff","#000000"); 289 for(int i=0;i<len;i++) { 290 table.appendRow(1,new SimpleDumpData(i),toDumpData(list.item(i),pageContext,maxlevel,props)); 291 } 292 return setId(id,table); 293 294 } 295 // AttributeMap 296 if(o instanceof AttributeMap) { 297 return setId(id,new XMLAttributes((AttributeMap)o,false).toDumpData(pageContext, maxlevel,props)); 298 } 299 // HttpSession 300 if(o instanceof HttpSession) { 301 HttpSession hs = (HttpSession)o; 302 Enumeration e = hs.getAttributeNames(); 303 304 DumpTable htmlBox = new DumpTablePro("httpsession","#9999ff","#ccccff","#000000"); 305 htmlBox.setTitle("HttpSession"); 306 while(e.hasMoreElements()) { 307 String key=e.nextElement().toString(); 308 htmlBox.appendRow(1,new SimpleDumpData(key),toDumpData(hs.getAttribute(key), pageContext,maxlevel,props)); 309 } 310 return setId(id,htmlBox); 311 } 312 313 314 // reflect 315 //else { 316 DumpTable table = new DumpTablePro(o.getClass().getName(),"#cc9999","#ffcccc","#000000"); 317 318 Class clazz=o.getClass(); 319 if(o instanceof Class) clazz=(Class) o; 320 String fullClassName=clazz.getName(); 321 int pos=fullClassName.lastIndexOf('.'); 322 String className=pos==-1?fullClassName:fullClassName.substring(pos+1); 323 324 table.setTitle(className); 325 table.appendRow(1,new SimpleDumpData("class"),new SimpleDumpData(fullClassName)); 326 327 // Fields 328 Field[] fields=clazz.getFields(); 329 DumpTable fieldDump = new DumpTable("#cc9999","#ffcccc","#000000"); 330 fieldDump.appendRow(7,new SimpleDumpData("name"),new SimpleDumpData("pattern"),new SimpleDumpData("value")); 331 for(int i=0;i<fields.length;i++) { 332 Field field = fields[i]; 333 DumpData value; 334 try {//print.out(o+":"+maxlevel); 335 value=new SimpleDumpData(Caster.toString(field.get(o), "")); 336 } 337 catch (Exception e) { 338 value=new SimpleDumpData(""); 339 } 340 fieldDump.appendRow(0,new SimpleDumpData(field.getName()),new SimpleDumpData(field.toString()),value); 341 } 342 if(fields.length>0)table.appendRow(1,new SimpleDumpData("fields"),fieldDump); 343 344 // Methods 345 StringBuffer objMethods=new StringBuffer(); 346 Method[] methods=clazz.getMethods(); 347 DumpTable methDump = new DumpTable("#cc9999","#ffcccc","#000000"); 348 methDump.appendRow(7,new SimpleDumpData("return"),new SimpleDumpData("interface"),new SimpleDumpData("exceptions")); 349 for(int i=0;i<methods.length;i++) { 350 Method method = methods[i]; 351 352 if(Object.class==method.getDeclaringClass()) { 353 if(objMethods.length()>0)objMethods.append(", "); 354 objMethods.append(method.getName()); 355 continue; 356 } 357 358 // exceptions 359 StringBuffer sbExp=new StringBuffer(); 360 Class[] exceptions = method.getExceptionTypes(); 361 for(int p=0;p<exceptions.length;p++){ 362 if(p>0)sbExp.append("\n"); 363 sbExp.append(Caster.toClassName(exceptions[p])); 364 } 365 366 // parameters 367 StringBuffer sbParams=new StringBuffer(method.getName()); 368 sbParams.append('('); 369 Class[] parameters = method.getParameterTypes(); 370 for(int p=0;p<parameters.length;p++){ 371 if(p>0)sbParams.append(", "); 372 sbParams.append(Caster.toClassName(parameters[p])); 373 } 374 sbParams.append(')'); 375 376 methDump.appendRow(0, 377 new SimpleDumpData(Caster.toClassName(method.getReturnType())), 378 379 new SimpleDumpData(sbParams.toString()), 380 new SimpleDumpData(sbExp.toString()) 381 ); 382 } 383 if(methods.length>0)table.appendRow(1,new SimpleDumpData("methods"),methDump); 384 385 DumpTable inherited = new DumpTable("#cc9999","#ffcccc","#000000"); 386 inherited.appendRow(7,new SimpleDumpData("Methods inherited from java.lang.Object")); 387 inherited.appendRow(0,new SimpleDumpData(objMethods.toString())); 388 table.appendRow(1,new SimpleDumpData(""),inherited); 389 return setId(id,table); 390 //} 391 } 392 finally{ 393 ThreadLocalDump.remove(o); 394 } 395 } 396 397 private static DumpData setId(String id, DumpData data) { 398 if(data instanceof DumpTablePro) { 399 ((DumpTablePro)data).setId(id); 400 } 401 // TODO Auto-generated method stub 402 return data; 403 } 404 405 public static boolean keyValid(DumpProperties props,int level, String key) { 406 if(props.getMaxlevel()-level>1) return true; 407 408 // show 409 Set set = props.getShow(); 410 if(set!=null && !set.contains(StringUtil.toLowerCase(key))) 411 return false; 412 413 // hide 414 set = props.getHide(); 415 if(set!=null && set.contains(StringUtil.toLowerCase(key))) 416 return false; 417 418 return true; 419 } 420 421 public static boolean keyValid(DumpProperties props,int level, Collection.Key key) { 422 if(props.getMaxlevel()-level>1) return true; 423 424 // show 425 Set set = props.getShow(); 426 if(set!=null && !set.contains(key.getLowerString())) 427 return false; 428 429 // hide 430 set = props.getHide(); 431 if(set!=null && set.contains(key.getLowerString())) 432 return false; 433 434 return true; 435 } 436 437 438 439 440 public static DumpProperties toDumpProperties() { 441 return DumpProperties.DEFAULT; 442 } 443 }