001 package railo.runtime.debug; 002 003 import java.io.IOException; 004 import java.util.ArrayList; 005 import java.util.Collections; 006 import java.util.HashMap; 007 import java.util.Iterator; 008 import java.util.List; 009 import java.util.ListIterator; 010 import java.util.Map; 011 012 import railo.commons.io.log.LogUtil; 013 import railo.commons.lang.StringUtil; 014 import railo.runtime.PageContext; 015 import railo.runtime.PageSource; 016 import railo.runtime.config.Config; 017 import railo.runtime.config.ConfigWebImpl; 018 import railo.runtime.db.SQL; 019 import railo.runtime.dump.DumpData; 020 import railo.runtime.dump.DumpProperties; 021 import railo.runtime.dump.DumpRow; 022 import railo.runtime.dump.DumpTable; 023 import railo.runtime.dump.DumpUtil; 024 import railo.runtime.dump.Dumpable; 025 import railo.runtime.dump.SimpleDumpData; 026 import railo.runtime.exp.CatchBlock; 027 import railo.runtime.exp.DatabaseException; 028 import railo.runtime.exp.PageException; 029 import railo.runtime.exp.PageExceptionImpl; 030 import railo.runtime.interpreter.CFMLExpressionInterpreter; 031 import railo.runtime.op.Caster; 032 import railo.runtime.type.Array; 033 import railo.runtime.type.ArrayImpl; 034 import railo.runtime.type.Collection; 035 import railo.runtime.type.DebugQueryColumn; 036 import railo.runtime.type.KeyImpl; 037 import railo.runtime.type.Query; 038 import railo.runtime.type.QueryColumn; 039 import railo.runtime.type.QueryImpl; 040 import railo.runtime.type.Struct; 041 import railo.runtime.type.StructImpl; 042 043 044 /** 045 * Class to debug the application 046 */ 047 public final class DebuggerImpl implements Dumpable, Debugger { 048 049 private static final long serialVersionUID = 4103405920561543718L; 050 private static final Collection.Key PAGES = KeyImpl.intern("pages"); 051 private static final Collection.Key QUERIES = KeyImpl.intern("queries"); 052 private static final Collection.Key TIMERS = KeyImpl.intern("timers"); 053 private static final Collection.Key TRACES = KeyImpl.intern("traces"); 054 private static final Collection.Key HISTORY = KeyImpl.intern("history"); 055 private static final Collection.Key SQL = KeyImpl.intern("sql"); 056 private static final Collection.Key SRC = KeyImpl.intern("src"); 057 private static final Collection.Key COUNT = KeyImpl.intern("count"); 058 private static final Collection.Key DATASOURCE = KeyImpl.intern("datasource"); 059 private static final Collection.Key USAGE = KeyImpl.intern("usage"); 060 061 private Map<String,DebugEntryImpl> pages=new HashMap<String,DebugEntryImpl>(); 062 private List<QueryEntryImpl> queries=new ArrayList<QueryEntryImpl>(); 063 private List<DebugTimerImpl> timers=new ArrayList<DebugTimerImpl>(); 064 private List<DebugTraceImpl> traces=new ArrayList<DebugTraceImpl>(); 065 private List<CatchBlock> exceptions=new ArrayList<CatchBlock>(); 066 067 private boolean output=true; 068 private long lastEntry; 069 private long lastTrace; 070 private Array historyId=new ArrayImpl(); 071 private Array historyLevel=new ArrayImpl(); 072 073 /** 074 * @see railo.runtime.debug.Debugger#reset() 075 */ 076 public void reset() { 077 pages.clear(); 078 queries.clear(); 079 timers.clear(); 080 traces.clear(); 081 exceptions.clear(); 082 historyId.clear(); 083 historyLevel.clear(); 084 output=true; 085 } 086 087 /** 088 * standart Constructor of the class 089 */ 090 public DebuggerImpl() { 091 092 } 093 094 /** 095 * 096 * @see railo.runtime.debug.Debugger#getEntry(railo.runtime.PageContext, railo.runtime.PageSource) 097 */ 098 public DebugEntry getEntry(PageContext pc,PageSource source) { 099 return getEntry(pc,source,null); 100 } 101 102 /** 103 * 104 * @see railo.runtime.debug.Debugger#getEntry(railo.runtime.PageContext, railo.runtime.PageSource, java.lang.String) 105 */ 106 public DebugEntry getEntry(PageContext pc,PageSource source, String key) { 107 lastEntry = System.currentTimeMillis(); 108 String src=DebugEntryImpl.getSrc(source,key); 109 110 DebugEntryImpl de=(DebugEntryImpl) pages.get(src); 111 if(de!=null ){ 112 de.countPP(); 113 historyId.appendEL(de.getId()); 114 historyLevel.appendEL(Caster.toInteger(pc.getCurrentLevel())); 115 return de; 116 } 117 de=new DebugEntryImpl(source,key); 118 pages.put(src,de); 119 historyId.appendEL(de.getId()); 120 historyLevel.appendEL(Caster.toInteger(pc.getCurrentLevel())); 121 return de; 122 } 123 124 /** 125 * @see railo.runtime.dump.Dumpable#toDumpData(railo.runtime.PageContext, int) 126 */ 127 public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) { 128 if(!output) return null; 129 130 // fill pages to aray 131 ArrayList<DebugEntry> arrPages = toArray(); 132 QueryEntry[] arrQueries=(QueryEntry[]) queries.toArray(new QueryEntry[queries.size()]); 133 134 135 DumpTable boxPage = new DumpTable("#cccccc","#ffffff","#000000"); 136 boxPage.setWidth("100%"); 137 138 int len=arrPages.size(); 139 int tLoad=0; 140 int tQuery=0; 141 int tApp=0; 142 int tCount=0; 143 for(int i=0;i<len;i++) { 144 DebugEntry de=(DebugEntry) arrPages.get(i); 145 tLoad+=de.getFileLoadTime(); 146 tQuery+=de.getQueryTime(); 147 tApp+=de.getExeTime(); 148 tCount+=de.getCount(); 149 boxPage.appendRow(new DumpRow(0,new DumpData[]{ 150 new SimpleDumpData(de.getSrc()), 151 new SimpleDumpData(String.valueOf(de.getCount())), 152 //plus(de.getMin()),//Min 153 //plus(de.getExeTime()/de.getCount()), 154 //plus(de.getMax()),//Max 155 _toDumpData(de.getFileLoadTime()), 156 _toDumpData(de.getQueryTime()), 157 new SimpleDumpData(_toDumpData(de.getExeTime()-de.getQueryTime())+""), 158 new SimpleDumpData(""), 159 _toDumpData(de.getFileLoadTime()+de.getExeTime())})); 160 161 } 162 // Total 163 DumpRow row = new DumpRow(1023,new DumpData[]{new SimpleDumpData("Total"),_toDumpData(tCount),_toDumpData(tLoad),_toDumpData(tQuery),_toDumpData(tApp-tQuery),new SimpleDumpData(""),_toDumpData(tLoad+tApp)}); 164 boxPage.appendRow(row); 165 boxPage.prependRow(row); 166 167 row=new DumpRow(1023,new DumpData[]{new SimpleDumpData("file"),new SimpleDumpData("count"),new SimpleDumpData("load"),new SimpleDumpData("query"),new SimpleDumpData("app"),new SimpleDumpData(""),new SimpleDumpData("total")}); 168 boxPage.appendRow(row); 169 boxPage.prependRow(row); 170 171 // Exceptions 172 DumpTable tableExceptions=null; 173 int tl=exceptions==null?0:exceptions.size(); 174 if(tl>0) { 175 tableExceptions = new DumpTable("#cccccc","#ffffff","#000000"); 176 177 tableExceptions.appendRow(15, new SimpleDumpData("type"),new SimpleDumpData("message"),new SimpleDumpData("detail"), new SimpleDumpData("template")); 178 179 180 Iterator<CatchBlock> it = exceptions.iterator(); 181 CatchBlock block; 182 PageException pe; 183 String type,msg,detail,templ; 184 while(it.hasNext()) { 185 block=it.next(); 186 pe=block.getPageException(); 187 type=StringUtil.emptyIfNull(pe.getTypeAsString()); 188 msg=StringUtil.emptyIfNull(pe.getMessage()); 189 detail=StringUtil.emptyIfNull(pe.getDetail()); 190 templ=getTemplate(pageContext.getConfig(),pe,true); 191 tableExceptions.appendRow(0, 192 new SimpleDumpData(type), 193 new SimpleDumpData(msg), 194 new SimpleDumpData(detail), 195 new SimpleDumpData(templ)) ; 196 } 197 } 198 199 // Timers 200 DumpTable tableTimer=null; 201 tl=timers==null?0:timers.size(); 202 if(tl>0) { 203 tableTimer = new DumpTable("#cccccc","#ffffff","#000000"); 204 //boxTimer.setWidth("100%"); 205 tableTimer.appendRow(7, new SimpleDumpData("label"), new SimpleDumpData("time (ms)"),new SimpleDumpData("template")); 206 207 208 Iterator<DebugTimerImpl> it = timers.iterator(); 209 DebugTimer timer; 210 while(it.hasNext()) { 211 timer=(DebugTimer) it.next(); 212 tableTimer.appendRow(0, new SimpleDumpData(timer.getLabel()),new SimpleDumpData(timer.getTime()),new SimpleDumpData(timer.getTemplate())) ; 213 } 214 } 215 216 // Traces 217 DumpTable tableTraces=null; 218 tl=traces==null?0:traces.size(); 219 if(tl>0) { 220 tableTraces = new DumpTable("#cccccc","#ffffff","#000000"); 221 tableTraces.setWidth("100%"); 222 tableTraces.appendRow( 223 new DumpRow(2047, 224 new DumpData[]{ 225 new SimpleDumpData("type"), 226 new SimpleDumpData("category"), 227 new SimpleDumpData("text"), 228 new SimpleDumpData("template"), 229 new SimpleDumpData("line"), 230 new SimpleDumpData("action"), 231 new SimpleDumpData("var name"), 232 new SimpleDumpData("var value"), 233 new SimpleDumpData("total time (ms)"), 234 new SimpleDumpData("trace slot time (ms)")})); 235 236 Iterator<DebugTraceImpl> it = traces.iterator(); 237 DebugTraceImpl trace; 238 int total=0; 239 while(it.hasNext()) { 240 trace=(DebugTraceImpl) it.next(); 241 total+=trace.getTime(); 242 DumpTable tableVar=new DumpTable("#cccccc","#ffffff","#000000"); 243 SimpleDumpData varValue = new SimpleDumpData(toString(trace.getVarValue())); 244 DumpData var; 245 try { 246 Object value = new CFMLExpressionInterpreter().interpret(pageContext,toString(trace.getVarValue())); 247 tableVar.appendRow(0, varValue); 248 tableVar.appendRow(0,DumpUtil.toDumpData(value, pageContext, maxlevel,dp) ); 249 var=tableVar; 250 } 251 catch(Throwable t) { 252 var=varValue; 253 } 254 255 tableTraces.appendRow(new DumpRow(0, new DumpData[]{ 256 new SimpleDumpData(LogUtil.toStringType(trace.getType(), "INFO")), 257 new SimpleDumpData(toString(trace.getCategory())), 258 new SimpleDumpData(toString(trace.getText())), 259 new SimpleDumpData(toString(trace.getTemplate())), 260 new SimpleDumpData(Caster.toString(trace.getLine())), 261 new SimpleDumpData(trace.getAction()), 262 new SimpleDumpData(toString(trace.getVarName())), 263 var, 264 new SimpleDumpData(Caster.toString(total)), 265 new SimpleDumpData(Caster.toString(trace.getTime()))})); 266 } 267 } 268 269 // Query 270 DumpTable tableQuery=null; 271 DumpTable tableQueryItem = null; 272 if(arrQueries.length>0) { 273 274 tableQuery = new DumpTable("#cccccc","#ffffff","#000000"); 275 tableQuery.setWidth("100%"); 276 277 for(int i=0;i<arrQueries.length;i++) { 278 tableQueryItem = new DumpTable("#cccccc","#ffffff","#000000"); 279 tableQueryItem.appendRow(1, new SimpleDumpData("Source"), new SimpleDumpData(arrQueries[i].getSrc())); 280 tableQueryItem.appendRow(1, new SimpleDumpData("Execution Time"), new SimpleDumpData(arrQueries[i].getExe())); 281 tableQueryItem.appendRow(1, new SimpleDumpData("Recordcount"), new SimpleDumpData(arrQueries[i].getRecordcount())); 282 tableQueryItem.appendRow(1, new SimpleDumpData("SQL"), new SimpleDumpData((arrQueries[i].getSQL().toString().trim()))); 283 284 // usage 285 try { 286 String usage = getUsageList(arrQueries[i]); 287 if(!StringUtil.isEmpty(usage)) { 288 tableQueryItem.appendRow(1, new SimpleDumpData("Columns not read"), new SimpleDumpData(usage)); 289 } 290 } catch (PageException e) {} 291 292 293 294 295 tableQuery.appendRow(0,tableQueryItem); 296 } 297 } 298 299 DumpTable table = new DumpTable("#cccccc","#ffffff","#000000"); 300 table.setTitle("Debugging Output"); 301 table.setWidth("100%"); 302 table.appendRow(1,new SimpleDumpData("Pages"),boxPage); 303 304 305 if(tableExceptions!=null && !tableExceptions.isEmpty())table.appendRow(1,new SimpleDumpData("Caught Exceptions"),tableExceptions); 306 if(tableTimer!=null && !tableTimer.isEmpty())table.appendRow(1,new SimpleDumpData("Timers"),tableTimer); 307 if(tableTraces!=null && !tableTraces.isEmpty())table.appendRow(1,new SimpleDumpData("Traces"),tableTraces); 308 if(tableQuery!=null && !tableQuery.isEmpty())table.appendRow(1,new SimpleDumpData("Queries"),tableQuery); 309 310 return table; 311 } 312 313 private String getTemplate(Config config,PageException pe,boolean withLine) { 314 try { 315 Array arr = ((PageExceptionImpl)pe).getTagContext(config); 316 Struct sct=Caster.toStruct(arr.getE(1)); 317 318 String templ= Caster.toString(sct.get(KeyImpl.TEMPLATE)); 319 if(withLine)templ +=":"+ Caster.toString(sct.get(KeyImpl.LINE)); 320 return templ; 321 } 322 catch (Throwable t) {} 323 324 return ""; 325 } 326 327 private String toString(Object o) { 328 if(o==null) return ""; 329 return Caster.toString(o,""); 330 } 331 332 private ArrayList<DebugEntry> toArray() { 333 ArrayList<DebugEntry> arrPages=new ArrayList<DebugEntry>(pages.size()); 334 Iterator<String> it = pages.keySet().iterator(); 335 while(it.hasNext()) { 336 DebugEntry page = (DebugEntry) pages.get(it.next()); 337 page.resetQueryTime(); 338 arrPages.add(page); 339 340 } 341 342 Collections.sort(arrPages,new DebugEntryComparator()); 343 344 345 // Queries 346 int len=queries.size(); 347 for(int i=0;i<len;i++) { 348 QueryEntry entry=(QueryEntry) queries.get(i); 349 String path=entry.getSrc(); 350 Object o=pages.get(path); 351 352 if(o!=null) { 353 DebugEntry oe=(DebugEntry) o; 354 oe.updateQueryTime(entry.getExe()); 355 } 356 } 357 358 return arrPages; 359 } 360 361 private DumpData _toDumpData(int value) { 362 return new SimpleDumpData(_toString(value)); 363 } 364 private String _toString(int value) { 365 if(value<=0) return "0"; 366 return String.valueOf(value); 367 } 368 369 /** 370 * @see railo.runtime.debug.Debugger#addQueryExecutionTime(java.lang.String, java.lang.String, railo.runtime.db.SQL, int, railo.runtime.PageSource, int) 371 */ 372 // FUTURE set deprecated 373 public void addQueryExecutionTime(String datasource,String name,SQL sql, int recordcount, PageSource src,int time) { 374 queries.add(new QueryEntryImpl(null,datasource,name,sql,recordcount,src.getDisplayPath(),time)); 375 } 376 377 // FUTURE add to interface 378 public void addQuery(Query query,String datasource,String name,SQL sql, int recordcount, PageSource src,int time) { 379 queries.add(new QueryEntryImpl(query,datasource,name,sql,recordcount,src.getDisplayPath(),time)); 380 } 381 382 /** 383 * @see railo.runtime.debug.Debugger#setOutput(boolean) 384 */ 385 public void setOutput(boolean output) { 386 this.output = output; 387 } 388 389 /** 390 * @see railo.runtime.debug.Debugger#getQueries() 391 */ 392 public List<QueryEntryImpl> getQueries() { 393 return queries; 394 } 395 396 /** 397 * @see railo.runtime.debug.Debugger#writeOut(railo.runtime.PageContext) 398 */ 399 public void writeOut(PageContext pc) throws IOException { 400 //stop(); 401 if(!output)return; 402 403 String template=pc.getConfig().getDebugTemplate(); 404 405 // no debug File 406 if(StringUtil.isEmpty(template)) { 407 pc.forceWrite(pc.getConfig().getDefaultDumpWriter().toString(pc,toDumpData(pc, 9999,DumpUtil.toDumpProperties()),true)); 408 return; 409 } 410 try { 411 pc.doInclude(template); 412 } 413 catch (PageException e) { 414 pc.handlePageException(e); 415 } 416 } 417 418 /** 419 * @see railo.runtime.debug.Debugger#getDebuggingData() 420 */ 421 public Struct getDebuggingData() { 422 List<QueryEntryImpl> queries = getQueries(); 423 Struct qryExe=new StructImpl(); 424 ListIterator<QueryEntryImpl> qryIt = queries.listIterator(); 425 String[] cols = new String[]{"name","time","sql","src","count","datasource","usage"}; 426 String[] types = new String[]{"VARCHAR","DOUBLE","VARCHAR","VARCHAR","DOUBLE","VARCHAR","ANY"}; 427 428 //queries 429 Query qryQueries=null; 430 try { 431 qryQueries = new QueryImpl(cols,types,queries.size(),"query"); 432 } catch (DatabaseException e) { 433 qryQueries = new QueryImpl(cols,queries.size(),"query"); 434 } 435 int row=0; 436 try { 437 while(qryIt.hasNext()) { 438 row++; 439 QueryEntry qe=(QueryEntry) qryIt.next(); 440 qryQueries.setAt(KeyImpl.NAME,row,qe.getName()==null?"":qe.getName()); 441 qryQueries.setAt(KeyImpl.TIME,row,Integer.valueOf(qe.getExe())); 442 qryQueries.setAt(SQL,row,qe.getSQL().toString()); 443 qryQueries.setAt(SRC,row,qe.getSrc()); 444 qryQueries.setAt(COUNT,row,Integer.valueOf(qe.getRecordcount())); 445 qryQueries.setAt(DATASOURCE,row,qe.getDatasource()); 446 447 Struct usage = getUsage(qe); 448 if(usage!=null) qryQueries.setAt(USAGE,row,usage); 449 450 451 452 Object o=qryExe.get(KeyImpl.init(qe.getSrc()),null); 453 if(o==null) qryExe.setEL(KeyImpl.init(qe.getSrc()),Integer.valueOf(qe.getExe())); 454 else qryExe.setEL(KeyImpl.init(qe.getSrc()),Integer.valueOf(((Integer)o).intValue()+qe.getExe())); 455 } 456 } 457 catch(PageException dbe) {} 458 459 // Pages 460 // src,load,app,query,total 461 Struct debugging=new StructImpl(); 462 463 row=0; 464 ArrayList<DebugEntry> arrPages = toArray(); 465 int len=arrPages.size(); 466 Query qryPage=new QueryImpl( 467 new String[]{"id","count","min","max","avg","app","load","query","total","src"}, 468 len,"query"); 469 470 try { 471 DebugEntry de; 472 //PageSource ps; 473 for(int i=0;i<len;i++) { 474 row++; 475 de=(DebugEntry) arrPages.get(i); 476 //ps = de.getPageSource(); 477 478 qryPage.setAt("id",row,de.getId()); 479 qryPage.setAt("count",row,_toString(de.getCount())); 480 qryPage.setAt("min",row,_toString(de.getMin())); 481 qryPage.setAt("max",row,_toString(de.getMax())); 482 qryPage.setAt("avg",row,_toString(de.getExeTime()/de.getCount())); 483 qryPage.setAt("app",row,_toString(de.getExeTime()-de.getQueryTime())); 484 qryPage.setAt("load",row,_toString(de.getFileLoadTime())); 485 qryPage.setAt("query",row,_toString(de.getQueryTime())); 486 qryPage.setAt(KeyImpl.TOTAL,row,_toString(de.getFileLoadTime()+de.getExeTime())); 487 qryPage.setAt("src",row,de.getSrc()); 488 } 489 } 490 catch(PageException dbe) {} 491 492 // exceptions 493 len=exceptions==null?0:exceptions.size(); 494 495 Array arrExceptions=new ArrayImpl(); 496 if(len>0) { 497 Iterator<CatchBlock> it = exceptions.iterator(); 498 row=0; 499 while(it.hasNext()) { 500 arrExceptions.appendEL(it.next()); 501 } 502 503 } 504 505 // timers 506 len=timers==null?0:timers.size(); 507 Query qryTimers=new QueryImpl( 508 new String[]{"label","time","template"}, 509 len,"timers"); 510 if(len>0) { 511 try { 512 Iterator<DebugTimerImpl> it = timers.iterator(); 513 DebugTimer timer; 514 row=0; 515 while(it.hasNext()) { 516 timer=(DebugTimer) it.next(); 517 row++; 518 qryTimers.setAt(KeyImpl.LABEL,row,timer.getLabel()); 519 qryTimers.setAt(KeyImpl.TEMPLATE,row,timer.getTemplate()); 520 qryTimers.setAt(KeyImpl.TIME,row,Caster.toDouble(timer.getTime())); 521 } 522 } 523 catch(PageException dbe) {} 524 } 525 526 // traces 527 len=traces==null?0:traces.size(); 528 Query qryTraces=new QueryImpl( 529 new String[]{"type","category","text","template","line","action","varname","varvalue","time"}, 530 len,"traces"); 531 if(len>0) { 532 try { 533 Iterator<DebugTraceImpl> it = traces.iterator(); 534 DebugTraceImpl trace; 535 row=0; 536 while(it.hasNext()) { 537 trace= it.next(); 538 row++; 539 qryTraces.setAt(KeyImpl.TYPE,row,LogUtil.toStringType(trace.getType(), "INFO")); 540 if(!StringUtil.isEmpty(trace.getCategory()))qryTraces.setAt("category",row,trace.getCategory()); 541 if(!StringUtil.isEmpty(trace.getText()))qryTraces.setAt("text",row,trace.getText()); 542 if(!StringUtil.isEmpty(trace.getTemplate()))qryTraces.setAt(KeyImpl.TEMPLATE,row,trace.getTemplate()); 543 if(trace.getLine()>0)qryTraces.setAt(KeyImpl.LINE,row,new Double(trace.getLine())); 544 if(!StringUtil.isEmpty(trace.getAction()))qryTraces.setAt("action",row,trace.getAction()); 545 if(!StringUtil.isEmpty(trace.getVarName()))qryTraces.setAt("varname",row,trace.getVarName()); 546 if(!StringUtil.isEmpty(trace.getVarValue()))qryTraces.setAt("varvalue",row,trace.getVarValue()); 547 qryTraces.setAt(KeyImpl.TIME,row,new Double(trace.getTime())); 548 } 549 } 550 catch(PageException dbe) {} 551 } 552 553 Query history=new QueryImpl(new String[]{},0,"history"); 554 try { 555 history.addColumn(KeyImpl.ID, historyId); 556 history.addColumn("level", historyLevel); 557 } catch (PageException e) { 558 } 559 560 debugging.setEL(PAGES,qryPage); 561 debugging.setEL(QUERIES,qryQueries); 562 debugging.setEL(TIMERS,qryTimers); 563 debugging.setEL(TRACES,qryTraces); 564 debugging.setEL(HISTORY,history); 565 debugging.setEL(KeyImpl.EXCEPTIONS,arrExceptions); 566 //debugging.setEL(TRACE_OBJECTS,arrTO); 567 return debugging; 568 } 569 570 571 572 573 private static Struct getUsage(QueryEntry qe) throws PageException { 574 Query qry = ((QueryEntryImpl)qe).getQry(); 575 576 QueryColumn c; 577 DebugQueryColumn dqc; 578 outer:if(qry!=null) { 579 Struct usage=null; 580 String[] columnNames = qry.getColumns(); 581 Collection.Key colName; 582 for(int i=0;i<columnNames.length;i++){ 583 colName=KeyImpl.init(columnNames[i]); 584 c = qry.getColumn(colName); 585 if(!(c instanceof DebugQueryColumn)) break outer; 586 dqc=(DebugQueryColumn) c; 587 if(usage==null) usage=new StructImpl(); 588 usage.setEL(colName, Caster.toBoolean(dqc.isUsed())); 589 } 590 return usage; 591 } 592 return null; 593 } 594 595 596 private static String getUsageList(QueryEntry qe) throws PageException { 597 Query qry = ((QueryEntryImpl)qe).getQry(); 598 StringBuilder sb=new StringBuilder(); 599 QueryColumn c; 600 DebugQueryColumn dqc; 601 outer:if(qry!=null) { 602 String[] columnNames = qry.getColumns(); 603 Collection.Key colName; 604 for(int i=0;i<columnNames.length;i++){ 605 colName=KeyImpl.init(columnNames[i]); 606 c = qry.getColumn(colName); 607 if(!(c instanceof DebugQueryColumn)) break outer; 608 dqc=(DebugQueryColumn) c; 609 if(!dqc.isUsed()){ 610 if(sb.length()>0) sb.append(", "); 611 sb.append(colName.getString()); 612 } 613 } 614 } 615 return sb.toString(); 616 } 617 618 /** 619 * @see railo.runtime.debug.Debugger#addTimer(java.lang.String, long, java.lang.String) 620 */ 621 public DebugTimer addTimer(String label, long time, String template) { 622 DebugTimerImpl t; 623 timers.add(t=new DebugTimerImpl(label,time,template)); 624 return t; 625 } 626 627 /** 628 * @see railo.runtime.debug.Debugger#addTrace(int, java.lang.String, java.lang.String, railo.runtime.PageSource, java.lang.String) 629 */ 630 public DebugTrace addTrace(int type, String category, String text, PageSource page,String varName,String varValue) { 631 632 long _lastTrace =(traces.isEmpty())?lastEntry: lastTrace; 633 lastTrace = System.currentTimeMillis(); 634 StackTraceElement[] _traces = new Exception("Stack trace").getStackTrace(); 635 String clazz=page.getFullClassName(); 636 int line=0; 637 638 // line 639 for(int i=0;i<_traces.length;i++) { 640 StackTraceElement trace=_traces[i]; 641 if(trace.getClassName().startsWith(clazz)) { 642 line=trace.getLineNumber(); 643 } 644 } 645 646 DebugTraceImpl t; 647 traces.add(t=new DebugTraceImpl(type,category,text,page.getDisplayPath(),line,"",varName,varValue,lastTrace-_lastTrace)); 648 return t; 649 } 650 651 public DebugTrace addTrace(int type, String category, String text, String template,int line,String action,String varName,String varValue) { 652 653 long _lastTrace =(traces.isEmpty())?lastEntry: lastTrace; 654 lastTrace = System.currentTimeMillis(); 655 656 DebugTraceImpl t; 657 traces.add(t=new DebugTraceImpl(type,category,text,template,line,action,varName,varValue,lastTrace-_lastTrace)); 658 return t; 659 } 660 661 /** 662 * 663 * @see railo.runtime.debug.Debugger#getTraces() 664 */ 665 public DebugTrace[] getTraces() { 666 return traces.toArray(new DebugTrace[traces.size()]); 667 } 668 669 // FUTURE add to interface 670 public void addException(Config config,PageException pe) { 671 if(exceptions.size()>1000) return; 672 try { 673 exceptions.add(((PageExceptionImpl)pe).getCatchBlock(config)); 674 } 675 catch(Throwable t){} 676 } 677 678 679 // FUTURE add to interface 680 public CatchBlock[] getExceptions() { 681 return exceptions.toArray(new CatchBlock[exceptions.size()]); 682 } 683 684 public static boolean debugQueryUsage(PageContext pageContext, Query query) { 685 if(pageContext.getConfig().debug() && query instanceof QueryImpl) { 686 if(((ConfigWebImpl)pageContext.getConfig()).getDebugShowQueryUsage()){ 687 ((QueryImpl)query).enableShowQueryUsage(); 688 return true; 689 } 690 } 691 return false; 692 } 693 694 }