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.w3c.dom.NamedNodeMap; 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.XMLCaster; 035 import railo.runtime.type.Array; 036 import railo.runtime.type.Collection; 037 import railo.runtime.type.ObjectWrap; 038 import railo.runtime.type.QueryImpl; 039 import railo.runtime.type.dt.DateTimeImpl; 040 import railo.runtime.type.scope.CookieImpl; 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("maximum dump level reached"); 048 } 049 // null 050 if(o == null) { 051 DumpTable table=new DumpTable("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 DumpTable("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 DumpTable("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 DumpTable("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 DumpTable("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 DumpTable("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 DumpTable("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 DumpTable("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 DumpTable("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("httpOnly"),new SimpleDumpData(CookieImpl.isHTTPOnly(c))); 149 table.appendRow(1,new SimpleDumpData("comment"),new SimpleDumpData(c.getComment())); 150 return table; 151 } 152 // Resource 153 if(o instanceof Resource) { 154 DumpTable table = new DumpTable("resource","#ffcc00","#ffff66","#000000"); 155 table.appendRow(1,new SimpleDumpData("Resource"),new SimpleDumpData(o.toString())); 156 return table; 157 } 158 // byte[] 159 if(o instanceof byte[]) { 160 byte[] bytes=(byte[]) o; 161 162 DumpTable table = new DumpTable("array","#ff9900","#ffcc00","#000000"); 163 table.setTitle("Native Array ("+Caster.toClassName(o)+")"); 164 165 StringBuffer sb=new StringBuffer(); 166 for(int i=0;i<bytes.length;i++) { 167 if(i!=0)sb.append("-"); 168 sb.append(bytes[i]); 169 if(i==1000) { 170 sb.append(" [truncated] "); 171 break; 172 } 173 } 174 table.appendRow(0,new SimpleDumpData(sb.toString())); 175 return table; 176 } 177 // Collection.Key 178 if(o instanceof Collection.Key) { 179 Collection.Key key=(Collection.Key) o; 180 DumpTable table = new DumpTable("string","#ff6600","#ffcc99","#000000"); 181 table.appendRow(1,new SimpleDumpData("Collection.Key"),new SimpleDumpData(key.getString())); 182 return table; 183 } 184 185 186 String id=""+IDGenerator.intId(); 187 String refid=ThreadLocalDump.get(o); 188 if(refid!=null) { 189 DumpTable table = new DumpTable("ref","#ffffff","#cccccc","#000000"); 190 table.appendRow(1,new SimpleDumpData("Reference"),new SimpleDumpData(refid)); 191 table.setRef(refid); 192 return setId(id,table); 193 } 194 195 ThreadLocalDump.set(o,id); 196 try{ 197 // Printable 198 if(o instanceof Dumpable) { 199 return setId(id,((Dumpable)o).toDumpData(pageContext,maxlevel,props)); 200 } 201 // Map 202 if(o instanceof Map) { 203 Map map=(Map) o; 204 Iterator it=map.keySet().iterator(); 205 206 DumpTable table = new DumpTable("struct","#ff9900","#ffcc00","#000000"); 207 table.setTitle("Map ("+Caster.toClassName(o)+")"); 208 209 while(it.hasNext()) { 210 Object next=it.next(); 211 table.appendRow(1,toDumpData(next,pageContext,maxlevel,props),toDumpData(map.get(next),pageContext,maxlevel,props)); 212 } 213 return setId(id,table); 214 } 215 216 // List 217 if(o instanceof List) { 218 List list=(List) o; 219 ListIterator it=list.listIterator(); 220 221 DumpTable table = new DumpTable("array","#ff9900","#ffcc00","#000000"); 222 table.setTitle("Array (List)"); 223 224 while(it.hasNext()) { 225 table.appendRow(1,new SimpleDumpData(it.nextIndex()+1),toDumpData(it.next(),pageContext,maxlevel,props)); 226 } 227 return setId(id,table); 228 } 229 230 // Set 231 if(o instanceof Set) { 232 Set set=(Set) o; 233 Iterator it = set.iterator(); 234 235 DumpTable table = new DumpTable("array","#ff9900","#ffcc00","#000000"); 236 table.setTitle("Set ("+set.getClass().getName()+")"); 237 238 while(it.hasNext()) { 239 table.appendRow(1,toDumpData(it.next(),pageContext,maxlevel,props)); 240 } 241 return setId(id,table); 242 } 243 244 // Resultset 245 if(o instanceof ResultSet) { 246 try { 247 DumpData dd = new QueryImpl((ResultSet)o,"query",pageContext.getTimeZone()).toDumpData(pageContext,maxlevel,props); 248 if(dd instanceof DumpTable) 249 ((DumpTable)dd).setTitle(Caster.toClassName(o)); 250 return setId(id,dd); 251 } 252 catch (PageException e) { 253 254 } 255 } 256 // Enumeration 257 if(o instanceof Enumeration) { 258 Enumeration e=(Enumeration)o; 259 260 DumpTable table = new DumpTable("enumeration","#ff9900","#ffcc00","#000000"); 261 table.setTitle("Enumeration"); 262 263 while(e.hasMoreElements()) { 264 table.appendRow(0,toDumpData(e.nextElement(),pageContext,maxlevel,props)); 265 } 266 return setId(id,table); 267 } 268 // Object[] 269 if(Decision.isNativeArray(o)) { 270 Array arr; 271 try { 272 arr = Caster.toArray(o); 273 DumpTable htmlBox = new DumpTable("array","#ff9900","#ffcc00","#000000"); 274 htmlBox.setTitle("Native Array ("+Caster.toClassName(o)+")"); 275 276 int length=arr.size(); 277 278 for(int i=1;i<=length;i++) { 279 Object ox=null; 280 try { 281 ox = arr.getE(i); 282 } catch (Exception e) {} 283 htmlBox.appendRow(1,new SimpleDumpData(i),toDumpData(ox,pageContext,maxlevel,props)); 284 } 285 return setId(id,htmlBox); 286 } 287 catch (PageException e) { 288 return setId(id,new SimpleDumpData("")); 289 } 290 } 291 // Node 292 if(o instanceof Node) { 293 return setId(id,XMLCaster.toDumpData((Node)o, pageContext,maxlevel,props)); 294 } 295 // ObjectWrap 296 if(o instanceof ObjectWrap) { 297 maxlevel++; 298 return setId(id,toDumpData(((ObjectWrap)o).getEmbededObject(null), pageContext,maxlevel,props)); 299 } 300 // NodeList 301 if(o instanceof NodeList) { 302 NodeList list=(NodeList)o; 303 int len=list.getLength(); 304 DumpTable table = new DumpTable("xml","#cc9999","#ffffff","#000000"); 305 for(int i=0;i<len;i++) { 306 table.appendRow(1,new SimpleDumpData(i),toDumpData(list.item(i),pageContext,maxlevel,props)); 307 } 308 return setId(id,table); 309 310 } 311 // AttributeMap 312 if(o instanceof NamedNodeMap) { 313 NamedNodeMap attr = (NamedNodeMap)o; 314 int len = attr.getLength(); 315 DumpTable dt = new DumpTable("array","#ff9900","#ffcc00","#000000"); 316 dt.setTitle("NamedNodeMap ("+Caster.toClassName(o)+")"); 317 318 for(int i=0;i<len;i++) { 319 dt.appendRow(1,new SimpleDumpData(i),toDumpData(attr.item(i),pageContext,maxlevel,props)); 320 } 321 return setId(id,dt); 322 } 323 // HttpSession 324 if(o instanceof HttpSession) { 325 HttpSession hs = (HttpSession)o; 326 Enumeration e = hs.getAttributeNames(); 327 328 DumpTable htmlBox = new DumpTable("httpsession","#9999ff","#ccccff","#000000"); 329 htmlBox.setTitle("HttpSession"); 330 while(e.hasMoreElements()) { 331 String key=e.nextElement().toString(); 332 htmlBox.appendRow(1,new SimpleDumpData(key),toDumpData(hs.getAttribute(key), pageContext,maxlevel,props)); 333 } 334 return setId(id,htmlBox); 335 } 336 337 338 // reflect 339 //else { 340 DumpTable table = new DumpTable(o.getClass().getName(),"#cc9999","#ffcccc","#000000"); 341 342 Class clazz=o.getClass(); 343 if(o instanceof Class) clazz=(Class) o; 344 String fullClassName=clazz.getName(); 345 int pos=fullClassName.lastIndexOf('.'); 346 String className=pos==-1?fullClassName:fullClassName.substring(pos+1); 347 348 table.setTitle(className); 349 table.appendRow(1,new SimpleDumpData("class"),new SimpleDumpData(fullClassName)); 350 351 // Fields 352 Field[] fields=clazz.getFields(); 353 DumpTable fieldDump = new DumpTable("#cc9999","#ffcccc","#000000"); 354 fieldDump.appendRow(7,new SimpleDumpData("name"),new SimpleDumpData("pattern"),new SimpleDumpData("value")); 355 for(int i=0;i<fields.length;i++) { 356 Field field = fields[i]; 357 DumpData value; 358 try {//print.out(o+":"+maxlevel); 359 value=new SimpleDumpData(Caster.toString(field.get(o), "")); 360 } 361 catch (Exception e) { 362 value=new SimpleDumpData(""); 363 } 364 fieldDump.appendRow(0,new SimpleDumpData(field.getName()),new SimpleDumpData(field.toString()),value); 365 } 366 if(fields.length>0)table.appendRow(1,new SimpleDumpData("fields"),fieldDump); 367 368 // Methods 369 StringBuffer objMethods=new StringBuffer(); 370 Method[] methods=clazz.getMethods(); 371 DumpTable methDump = new DumpTable("#cc9999","#ffcccc","#000000"); 372 methDump.appendRow(7,new SimpleDumpData("return"),new SimpleDumpData("interface"),new SimpleDumpData("exceptions")); 373 for(int i=0;i<methods.length;i++) { 374 Method method = methods[i]; 375 376 if(Object.class==method.getDeclaringClass()) { 377 if(objMethods.length()>0)objMethods.append(", "); 378 objMethods.append(method.getName()); 379 continue; 380 } 381 382 // exceptions 383 StringBuffer sbExp=new StringBuffer(); 384 Class[] exceptions = method.getExceptionTypes(); 385 for(int p=0;p<exceptions.length;p++){ 386 if(p>0)sbExp.append("\n"); 387 sbExp.append(Caster.toClassName(exceptions[p])); 388 } 389 390 // parameters 391 StringBuffer sbParams=new StringBuffer(method.getName()); 392 sbParams.append('('); 393 Class[] parameters = method.getParameterTypes(); 394 for(int p=0;p<parameters.length;p++){ 395 if(p>0)sbParams.append(", "); 396 sbParams.append(Caster.toClassName(parameters[p])); 397 } 398 sbParams.append(')'); 399 400 methDump.appendRow(0, 401 new SimpleDumpData(Caster.toClassName(method.getReturnType())), 402 403 new SimpleDumpData(sbParams.toString()), 404 new SimpleDumpData(sbExp.toString()) 405 ); 406 } 407 if(methods.length>0)table.appendRow(1,new SimpleDumpData("methods"),methDump); 408 409 DumpTable inherited = new DumpTable("#cc9999","#ffcccc","#000000"); 410 inherited.appendRow(7,new SimpleDumpData("Methods inherited from java.lang.Object")); 411 inherited.appendRow(0,new SimpleDumpData(objMethods.toString())); 412 table.appendRow(1,new SimpleDumpData(""),inherited); 413 return setId(id,table); 414 //} 415 } 416 finally{ 417 ThreadLocalDump.remove(o); 418 } 419 } 420 421 private static DumpData setId(String id, DumpData data) { 422 if(data instanceof DumpTable) { 423 ((DumpTable)data).setId(id); 424 } 425 // TODO Auto-generated method stub 426 return data; 427 } 428 429 public static boolean keyValid(DumpProperties props,int level, String key) { 430 if(props.getMaxlevel()-level>1) return true; 431 432 // show 433 Set set = props.getShow(); 434 if(set!=null && !set.contains(StringUtil.toLowerCase(key))) 435 return false; 436 437 // hide 438 set = props.getHide(); 439 if(set!=null && set.contains(StringUtil.toLowerCase(key))) 440 return false; 441 442 return true; 443 } 444 445 public static boolean keyValid(DumpProperties props,int level, Collection.Key key) { 446 if(props.getMaxlevel()-level>1) return true; 447 448 // show 449 Set set = props.getShow(); 450 if(set!=null && !set.contains(key.getLowerString())) 451 return false; 452 453 // hide 454 set = props.getHide(); 455 if(set!=null && set.contains(key.getLowerString())) 456 return false; 457 458 return true; 459 } 460 461 462 463 464 public static DumpProperties toDumpProperties() { 465 return DumpProperties.DEFAULT; 466 } 467 }