001 package railo.runtime.debug; 002 003 import java.io.IOException; 004 import java.util.ArrayList; 005 import java.util.Arrays; 006 import java.util.Collections; 007 import java.util.Comparator; 008 import java.util.HashMap; 009 import java.util.Iterator; 010 import java.util.List; 011 import java.util.ListIterator; 012 import java.util.Map; 013 014 import railo.commons.io.SystemUtil; 015 import railo.commons.io.log.LogUtil; 016 import railo.commons.lang.StringUtil; 017 import railo.runtime.Component; 018 import railo.runtime.Page; 019 import railo.runtime.PageContext; 020 import railo.runtime.PageContextImpl; 021 import railo.runtime.PageSource; 022 import railo.runtime.PageSourceImpl; 023 import railo.runtime.config.Config; 024 import railo.runtime.config.ConfigImpl; 025 import railo.runtime.config.ConfigWebImpl; 026 import railo.runtime.db.SQL; 027 import railo.runtime.engine.ThreadLocalPageContext; 028 import railo.runtime.exp.CatchBlock; 029 import railo.runtime.exp.DatabaseException; 030 import railo.runtime.exp.PageException; 031 import railo.runtime.exp.PageExceptionImpl; 032 import railo.runtime.op.Caster; 033 import railo.runtime.type.Array; 034 import railo.runtime.type.ArrayImpl; 035 import railo.runtime.type.Collection; 036 import railo.runtime.type.DebugQueryColumn; 037 import railo.runtime.type.KeyImpl; 038 import railo.runtime.type.Query; 039 import railo.runtime.type.QueryColumn; 040 import railo.runtime.type.QueryImpl; 041 import railo.runtime.type.Struct; 042 import railo.runtime.type.StructImpl; 043 import railo.runtime.type.dt.DateTimeImpl; 044 import railo.runtime.type.util.KeyConstants; 045 046 047 /** 048 * Class to debug the application 049 */ 050 public final class DebuggerImpl implements DebuggerPro { 051 private static final long serialVersionUID = 3957043879267494311L; 052 053 private static final Collection.Key IMPLICIT_ACCESS= KeyImpl.intern("implicitAccess"); 054 private static final Collection.Key PAGE_PARTS= KeyImpl.intern("pageParts"); 055 //private static final Collection.Key OUTPUT_LOG= KeyImpl.intern("outputLog"); 056 057 058 059 060 private static final int MAX_PARTS = 100; 061 062 private Map<String,DebugEntryTemplateImpl> entries=new HashMap<String,DebugEntryTemplateImpl>(); 063 private Map<String,DebugEntryTemplatePartImpl> partEntries; 064 private List<QueryEntry> queries=new ArrayList<QueryEntry>(); 065 private List<DebugTimerImpl> timers=new ArrayList<DebugTimerImpl>(); 066 private List<DebugTraceImpl> traces=new ArrayList<DebugTraceImpl>(); 067 private List<CatchBlock> exceptions=new ArrayList<CatchBlock>(); 068 private Map<String,ImplicitAccessImpl> implicitAccesses=new HashMap<String,ImplicitAccessImpl>(); 069 070 private boolean output=true; 071 private long lastEntry; 072 private long lastTrace; 073 private Array historyId=new ArrayImpl(); 074 private Array historyLevel=new ArrayImpl(); 075 076 private DateTimeImpl starttime; 077 078 079 private DebugOutputLog outputLog; 080 081 @Override 082 public void reset() { 083 entries.clear(); 084 if(partEntries!=null)partEntries.clear(); 085 queries.clear(); 086 implicitAccesses.clear(); 087 timers.clear(); 088 traces.clear(); 089 exceptions.clear(); 090 historyId.clear(); 091 historyLevel.clear(); 092 output=true; 093 outputLog=null; 094 } 095 096 public DebuggerImpl() { 097 } 098 099 @Override 100 public DebugEntryTemplate getEntry(PageContext pc,PageSource source) { 101 return getEntry(pc,source,null); 102 } 103 104 @Override 105 public DebugEntryTemplate getEntry(PageContext pc,PageSource source, String key) { 106 lastEntry = System.currentTimeMillis(); 107 String src=DebugEntryTemplateImpl.getSrc(source==null?"":source.getDisplayPath(),key); 108 109 DebugEntryTemplateImpl de= entries.get(src); 110 if(de!=null ){ 111 de.countPP(); 112 historyId.appendEL(de.getId()); 113 historyLevel.appendEL(Caster.toInteger(pc.getCurrentLevel())); 114 return de; 115 } 116 de=new DebugEntryTemplateImpl(source,key); 117 entries.put(src,de); 118 historyId.appendEL(de.getId()); 119 historyLevel.appendEL(Caster.toInteger(pc.getCurrentLevel())); 120 return de; 121 } 122 123 124 125 @Override 126 public DebugEntryTemplatePart getEntry(PageContext pc,PageSource source, int startPos, int endPos) { 127 String src=DebugEntryTemplatePartImpl.getSrc(source==null?"":source.getDisplayPath(),startPos,endPos); 128 DebugEntryTemplatePartImpl de=null; 129 if(partEntries!=null){ 130 de=partEntries.get(src); 131 if(de!=null ){ 132 de.countPP(); 133 return de; 134 } 135 } 136 else { 137 partEntries=new HashMap<String, DebugEntryTemplatePartImpl>(); 138 } 139 de=new DebugEntryTemplatePartImpl(source,startPos,endPos); 140 partEntries.put(src,de); 141 return de; 142 } 143 144 private ArrayList<DebugEntryTemplate> toArray() { 145 ArrayList<DebugEntryTemplate> arrPages=new ArrayList<DebugEntryTemplate>(entries.size()); 146 Iterator<String> it = entries.keySet().iterator(); 147 while(it.hasNext()) { 148 DebugEntryTemplate page =entries.get(it.next()); 149 page.resetQueryTime(); 150 arrPages.add(page); 151 152 } 153 Collections.sort(arrPages,new DebugEntryTemplateComparator()); 154 155 156 // Queries 157 int len=queries.size(); 158 for(int i=0;i<len;i++) { 159 QueryEntryPro entry=(QueryEntryPro) queries.get(i); 160 String path=entry.getSrc(); 161 Object o=entries.get(path); 162 163 if(o!=null) { 164 DebugEntryTemplate oe=(DebugEntryTemplate) o; 165 oe.updateQueryTime(entry.getExecutionTime()); 166 } 167 } 168 169 return arrPages; 170 } 171 172 /*private DumpData _toDumpData(int value) { 173 return new SimpleDumpData(_toString(value)); 174 } 175 private DumpData _toDumpData(long value) { 176 return new SimpleDumpData(_toString(value)); 177 }*/ 178 179 private String _toString(long value) { 180 if(value<=0) return "0"; 181 return String.valueOf(value); 182 } 183 private String _toString(int value) { 184 if(value<=0) return "0"; 185 return String.valueOf(value); 186 } 187 188 @Override 189 public void addQuery(Query query,String datasource,String name,SQL sql, int recordcount, PageSource src,int time) { 190 queries.add(new QueryEntryImpl(query,datasource,name,sql,recordcount,src.getDisplayPath(),time)); 191 } 192 193 @Override 194 public void addQuery(Query query,String datasource,String name,SQL sql, int recordcount, PageSource src,long time) { 195 queries.add(new QueryEntryImpl(query,datasource,name,sql,recordcount,src.getDisplayPath(),time)); 196 } 197 198 @Override 199 public void setOutput(boolean output) { 200 this.output = output; 201 } 202 203 @Override 204 public List<QueryEntry> getQueries() { 205 return queries; 206 } 207 208 @Override 209 public void writeOut(PageContext pc) throws IOException { 210 //stop(); 211 if(!output)return; 212 String addr = pc.getHttpServletRequest().getRemoteAddr(); 213 railo.runtime.config.DebugEntry debugEntry = ((ConfigImpl)pc.getConfig()).getDebugEntry(addr, null); 214 215 // no debug File 216 217 if(debugEntry==null) { 218 //pc.forceWrite(pc.getConfig().getDefaultDumpWriter().toString(pc,toDumpData(pc, 9999,DumpUtil.toDumpProperties()),true)); 219 return; 220 } 221 222 Struct args=new StructImpl(); 223 args.setEL(KeyConstants._custom, debugEntry.getCustom()); 224 try { 225 args.setEL(KeyConstants._debugging, pc.getDebugger().getDebuggingData(pc)); 226 } catch (PageException e1) {} 227 228 try { 229 PageSource[] arr = ((PageContextImpl)pc).getPageSources(debugEntry.getPath()); 230 Page p = PageSourceImpl.loadPage(pc, arr); 231 pc.addPageSource(p.getPageSource(), true); 232 try{ 233 Component cfc = pc.loadComponent(debugEntry.getFullname()); 234 cfc.callWithNamedValues(pc, "output", args); 235 } 236 finally { 237 pc.removeLastPageSource(true); 238 } 239 } 240 catch (PageException e) { 241 pc.handlePageException(e); 242 } 243 } 244 245 @Override 246 public Struct getDebuggingData(PageContext pc) throws DatabaseException { 247 return getDebuggingData(pc, false); 248 } 249 250 @Override 251 public Struct getDebuggingData(PageContext pc, boolean addAddionalInfo) throws DatabaseException { 252 List<QueryEntry> queries = getQueries(); 253 Struct qryExe=new StructImpl(); 254 ListIterator<QueryEntry> qryIt = queries.listIterator(); 255 Collection.Key[] cols = new Collection.Key[]{ 256 KeyConstants._name, 257 KeyConstants._time, 258 KeyConstants._sql, 259 KeyConstants._src, 260 KeyConstants._count, 261 KeyConstants._datasource, 262 KeyConstants._usage}; 263 String[] types = new String[]{"VARCHAR","DOUBLE","VARCHAR","VARCHAR","DOUBLE","VARCHAR","ANY"}; 264 265 //queries 266 Query qryQueries=null; 267 try { 268 qryQueries = new QueryImpl(cols,types,queries.size(),"query"); 269 } catch (DatabaseException e) { 270 qryQueries = new QueryImpl(cols,queries.size(),"query"); 271 } 272 int row=0; 273 try { 274 while(qryIt.hasNext()) { 275 row++; 276 QueryEntryPro qe=(QueryEntryPro) qryIt.next(); 277 qryQueries.setAt(KeyConstants._name,row,qe.getName()==null?"":qe.getName()); 278 qryQueries.setAt(KeyConstants._time,row,Long.valueOf(qe.getExecutionTime())); 279 qryQueries.setAt(KeyConstants._sql,row,qe.getSQL().toString()); 280 qryQueries.setAt(KeyConstants._src,row,qe.getSrc()); 281 qryQueries.setAt(KeyConstants._count,row,Integer.valueOf(qe.getRecordcount())); 282 qryQueries.setAt(KeyConstants._datasource,row,qe.getDatasource()); 283 284 Struct usage = getUsage(qe); 285 if(usage!=null) qryQueries.setAt(KeyConstants._usage,row,usage); 286 287 288 289 Object o=qryExe.get(KeyImpl.init(qe.getSrc()),null); 290 if(o==null) qryExe.setEL(KeyImpl.init(qe.getSrc()),Long.valueOf(qe.getExecutionTime())); 291 else qryExe.setEL(KeyImpl.init(qe.getSrc()),Long.valueOf(((Long)o).longValue()+qe.getExecutionTime())); 292 } 293 } 294 catch(PageException dbe) {} 295 296 // Pages 297 // src,load,app,query,total 298 Struct debugging=new StructImpl(); 299 row=0; 300 ArrayList<DebugEntryTemplate> arrPages = toArray(); 301 int len=arrPages.size(); 302 Query qryPage=new QueryImpl( 303 new Collection.Key[]{ 304 KeyConstants._id, 305 KeyConstants._count, 306 KeyConstants._min, 307 KeyConstants._max, 308 KeyConstants._avg 309 ,KeyConstants._app, 310 KeyConstants._load, 311 KeyConstants._query, 312 KeyConstants._total, 313 KeyConstants._src}, 314 len,"query"); 315 316 try { 317 DebugEntryTemplate de; 318 //PageSource ps; 319 for(int i=0;i<len;i++) { 320 row++; 321 de=arrPages.get(i); 322 //ps = de.getPageSource(); 323 324 qryPage.setAt(KeyConstants._id,row,de.getId()); 325 qryPage.setAt(KeyConstants._count,row,_toString(de.getCount())); 326 qryPage.setAt(KeyConstants._min,row,_toString(de.getMin())); 327 qryPage.setAt(KeyConstants._max,row,_toString(de.getMax())); 328 qryPage.setAt(KeyConstants._avg,row,_toString(de.getExeTime()/de.getCount())); 329 qryPage.setAt(KeyConstants._app,row,_toString(de.getExeTime()-de.getQueryTime())); 330 qryPage.setAt(KeyConstants._load,row,_toString(de.getFileLoadTime())); 331 qryPage.setAt(KeyConstants._query,row,_toString(de.getQueryTime())); 332 qryPage.setAt(KeyConstants._total,row,_toString( de.getFileLoadTime() + de.getExeTime())); 333 qryPage.setAt(KeyConstants._src,row,de.getSrc()); 334 } 335 } 336 catch(PageException dbe) {} 337 338 339 340 // Pages Parts 341 boolean hasParts=partEntries!=null && !partEntries.isEmpty(); 342 int qrySize=0; 343 if(hasParts) { 344 qrySize=partEntries.size()<MAX_PARTS?partEntries.size():MAX_PARTS; 345 } 346 347 Query qryPart=new QueryImpl( 348 new Collection.Key[]{ 349 KeyConstants._id 350 ,KeyConstants._count, 351 KeyConstants._min, 352 KeyConstants._max, 353 KeyConstants._avg, 354 KeyConstants._total, 355 KeyConstants._path, 356 KeyConstants._start, 357 KeyConstants._end}, 358 qrySize,"query"); 359 if(hasParts) { 360 row=0; 361 DebugEntryTemplatePart[] tmp = partEntries.values().toArray(new DebugEntryTemplatePart[partEntries.size()]); 362 Arrays.sort(tmp,new DebugEntryTemplatePartComparator()); 363 364 len=tmp.length<MAX_PARTS?tmp.length:MAX_PARTS; 365 DebugEntryTemplatePart[] parts=new DebugEntryTemplatePart[len]; 366 for(int i=0;i<len;i++) { 367 parts[i]=tmp[i]; 368 } 369 370 371 try { 372 DebugEntryTemplatePart de; 373 //PageSource ps; 374 for(int i=0;i<parts.length;i++) { 375 row++; 376 de=parts[i]; 377 378 qryPart.setAt(KeyConstants._id,row,de.getId()); 379 qryPart.setAt(KeyConstants._count,row,_toString(de.getCount())); 380 qryPart.setAt(KeyConstants._min,row,_toString(de.getMin())); 381 qryPart.setAt(KeyConstants._max,row,_toString(de.getMax())); 382 qryPart.setAt(KeyConstants._avg,row,_toString(de.getExeTime()/de.getCount())); 383 qryPart.setAt(KeyConstants._start,row,_toString(de.getStartPosition())); 384 qryPart.setAt(KeyConstants._end,row,_toString(de.getEndPosition())); 385 qryPart.setAt(KeyConstants._total,row,_toString(de.getExeTime())); 386 qryPart.setAt(KeyConstants._path,row,de.getPath()); 387 } 388 } 389 catch(PageException dbe) {} 390 } 391 392 393 394 395 // exceptions 396 len = exceptions==null?0:exceptions.size(); 397 398 Array arrExceptions=new ArrayImpl(); 399 if(len>0) { 400 Iterator<CatchBlock> it = exceptions.iterator(); 401 row=0; 402 while(it.hasNext()) { 403 arrExceptions.appendEL(it.next()); 404 } 405 406 } 407 408 // output log 409 //Query qryOutputLog=getOutputText(); 410 411 412 413 // timers 414 len=timers==null?0:timers.size(); 415 Query qryTimers=new QueryImpl( 416 new Collection.Key[]{KeyConstants._label,KeyConstants._time,KeyConstants._template}, 417 len,"timers"); 418 if(len>0) { 419 try { 420 Iterator<DebugTimerImpl> it = timers.iterator(); 421 DebugTimer timer; 422 row=0; 423 while(it.hasNext()) { 424 timer=it.next(); 425 row++; 426 qryTimers.setAt(KeyConstants._label,row,timer.getLabel()); 427 qryTimers.setAt(KeyConstants._template,row,timer.getTemplate()); 428 qryTimers.setAt(KeyConstants._time,row,Caster.toDouble(timer.getTime())); 429 } 430 } 431 catch(PageException dbe) {} 432 } 433 434 // traces 435 len=traces==null?0:traces.size(); 436 if(!((ConfigImpl)pc.getConfig()).hasDebugOptions(ConfigImpl.DEBUG_TRACING))len=0; 437 Query qryTraces=new QueryImpl( 438 new Collection.Key[]{ 439 KeyConstants._type, 440 KeyConstants._category, 441 KeyConstants._text, 442 KeyConstants._template, 443 KeyConstants._line, 444 KeyConstants._action, 445 KeyConstants._varname, 446 KeyConstants._varvalue, 447 KeyConstants._time}, 448 len,"traces"); 449 if(len>0) { 450 try { 451 Iterator<DebugTraceImpl> it = traces.iterator(); 452 DebugTraceImpl trace; 453 row=0; 454 while(it.hasNext()) { 455 trace= it.next(); 456 row++; 457 qryTraces.setAt(KeyConstants._type,row,LogUtil.toStringType(trace.getType(), "INFO")); 458 if(!StringUtil.isEmpty(trace.getCategory()))qryTraces.setAt(KeyConstants._category,row,trace.getCategory()); 459 if(!StringUtil.isEmpty(trace.getText()))qryTraces.setAt(KeyConstants._text,row,trace.getText()); 460 if(!StringUtil.isEmpty(trace.getTemplate()))qryTraces.setAt(KeyConstants._template,row,trace.getTemplate()); 461 if(trace.getLine()>0)qryTraces.setAt(KeyConstants._line,row,new Double(trace.getLine())); 462 if(!StringUtil.isEmpty(trace.getAction()))qryTraces.setAt(KeyConstants._action,row,trace.getAction()); 463 if(!StringUtil.isEmpty(trace.getVarName()))qryTraces.setAt(KeyImpl.init("varname"),row,trace.getVarName()); 464 if(!StringUtil.isEmpty(trace.getVarValue()))qryTraces.setAt(KeyImpl.init("varvalue"),row,trace.getVarValue()); 465 qryTraces.setAt(KeyConstants._time,row,new Double(trace.getTime())); 466 } 467 } 468 catch(PageException dbe) {} 469 } 470 471 472 473 // scope access 474 len=implicitAccesses==null?0:implicitAccesses.size(); 475 Query qryImplicitAccesseses=new QueryImpl( 476 new Collection.Key[]{ 477 KeyConstants._template, 478 KeyConstants._line, 479 KeyConstants._scope, 480 KeyConstants._count, 481 KeyConstants._name}, 482 len,"implicitAccess"); 483 if(len>0) { 484 try { 485 Iterator<ImplicitAccessImpl> it = implicitAccesses.values().iterator(); 486 ImplicitAccessImpl das; 487 row=0; 488 while(it.hasNext()) { 489 das= it.next(); 490 row++; 491 qryImplicitAccesseses.setAt(KeyConstants._template,row,das.getTemplate()); 492 qryImplicitAccesseses.setAt(KeyConstants._line,row,new Double(das.getLine())); 493 qryImplicitAccesseses.setAt(KeyConstants._scope,row,das.getScope()); 494 qryImplicitAccesseses.setAt(KeyConstants._count,row,new Double(das.getCount())); 495 qryImplicitAccesseses.setAt(KeyConstants._name,row,das.getName()); 496 497 } 498 } 499 catch(PageException dbe) {} 500 } 501 502 Query history=new QueryImpl(new Collection.Key[]{},0,"history"); 503 try { 504 history.addColumn(KeyConstants._id, historyId); 505 history.addColumn(KeyConstants._level, historyLevel); 506 } catch (PageException e) { 507 } 508 509 if(addAddionalInfo) { 510 debugging.setEL(KeyConstants._cgi,pc.cgiScope()); 511 debugging.setEL(KeyImpl.init("starttime"),starttime); 512 debugging.setEL(KeyConstants._id,pc.getId()); 513 } 514 515 debugging.setEL(KeyConstants._pages,qryPage); 516 debugging.setEL(PAGE_PARTS,qryPart); 517 debugging.setEL(KeyConstants._queries,qryQueries); 518 debugging.setEL(KeyConstants._timers,qryTimers); 519 debugging.setEL(KeyConstants._traces,qryTraces); 520 debugging.setEL(IMPLICIT_ACCESS,qryImplicitAccesseses); 521 //debugging.setEL(OUTPUT_LOG,qryOutputLog); 522 523 524 525 526 debugging.setEL(KeyConstants._history,history); 527 debugging.setEL(KeyConstants._exceptions,arrExceptions); 528 529 return debugging; 530 } 531 532 private static Struct getUsage(QueryEntry qe) throws PageException { 533 Query qry = ((QueryEntryImpl)qe).getQry(); 534 535 QueryColumn c; 536 DebugQueryColumn dqc; 537 outer:if(qry!=null) { 538 Struct usage=null; 539 Collection.Key[] columnNames = qry.getColumnNames(); 540 Collection.Key columnName; 541 for(int i=0;i<columnNames.length;i++){ 542 columnName=columnNames[i]; 543 c = qry.getColumn(columnName); 544 if(!(c instanceof DebugQueryColumn)) break outer; 545 dqc=(DebugQueryColumn) c; 546 if(usage==null) usage=new StructImpl(); 547 usage.setEL(columnName, Caster.toBoolean(dqc.isUsed())); 548 } 549 return usage; 550 } 551 return null; 552 } 553 554 /*private static String getUsageList(QueryEntry qe) throws PageException { 555 Query qry = ((QueryEntryImpl)qe).getQry(); 556 StringBuilder sb=new StringBuilder(); 557 QueryColumn c; 558 DebugQueryColumn dqc; 559 outer:if(qry!=null) { 560 String[] columnNames = qry.getColumns(); 561 Collection.Key colName; 562 for(int i=0;i<columnNames.length;i++){ 563 colName=KeyImpl.init(columnNames[i]); 564 c = qry.getColumn(colName); 565 if(!(c instanceof DebugQueryColumn)) break outer; 566 dqc=(DebugQueryColumn) c; 567 if(!dqc.isUsed()){ 568 if(sb.length()>0) sb.append(", "); 569 sb.append(colName.getString()); 570 } 571 } 572 } 573 return sb.toString(); 574 }*/ 575 576 @Override 577 public DebugTimer addTimer(String label, long time, String template) { 578 DebugTimerImpl t; 579 timers.add(t=new DebugTimerImpl(label,time,template)); 580 return t; 581 } 582 583 584 @Override 585 public DebugTrace addTrace(int type, String category, String text, PageSource page,String varName,String varValue) { 586 587 long _lastTrace =(traces.isEmpty())?lastEntry: lastTrace; 588 lastTrace = System.currentTimeMillis(); 589 StackTraceElement[] _traces = new Exception("Stack trace").getStackTrace(); 590 String clazz=page.getFullClassName(); 591 int line=0; 592 593 // line 594 for(int i=0;i<_traces.length;i++) { 595 StackTraceElement trace=_traces[i]; 596 if(trace.getClassName().startsWith(clazz)) { 597 line=trace.getLineNumber(); 598 break; 599 } 600 } 601 602 DebugTraceImpl t=new DebugTraceImpl(type,category,text,page.getDisplayPath(),line,"",varName,varValue,lastTrace-_lastTrace); 603 traces.add(t); 604 return t; 605 } 606 607 @Override 608 public DebugTrace addTrace(int type, String category, String text, String template,int line,String action,String varName,String varValue) { 609 610 long _lastTrace =(traces.isEmpty())?lastEntry: lastTrace; 611 lastTrace = System.currentTimeMillis(); 612 613 DebugTraceImpl t=new DebugTraceImpl(type,category,text,template,line,action,varName,varValue,lastTrace-_lastTrace); 614 traces.add(t); 615 return t; 616 } 617 618 @Override 619 public DebugTrace[] getTraces() { 620 return getTraces(ThreadLocalPageContext.get()); 621 } 622 623 public DebugTrace[] getTraces(PageContext pc) { 624 if(pc!=null && ((ConfigImpl)pc.getConfig()).hasDebugOptions(ConfigImpl.DEBUG_TRACING)) 625 return traces.toArray(new DebugTrace[traces.size()]); 626 return new DebugTrace[0]; 627 } 628 629 @Override 630 public void addException(Config config,PageException pe) { 631 if(exceptions.size()>1000) return; 632 try { 633 exceptions.add(((PageExceptionImpl)pe).getCatchBlock(config)); 634 } 635 catch(Throwable t){} 636 } 637 638 @Override 639 public CatchBlock[] getExceptions() { 640 return exceptions.toArray(new CatchBlock[exceptions.size()]); 641 } 642 643 public static boolean debugQueryUsage(PageContext pageContext, Query query) { 644 if(pageContext.getConfig().debug() && query instanceof QueryImpl) { 645 if(((ConfigWebImpl)pageContext.getConfig()).hasDebugOptions(ConfigImpl.DEBUG_QUERY_USAGE)){ 646 ((QueryImpl)query).enableShowQueryUsage(); 647 return true; 648 } 649 } 650 return false; 651 } 652 653 public void init(Config config) { 654 this.starttime=new DateTimeImpl(config); 655 } 656 657 @Override 658 public void addImplicitAccess(String scope, String name) { 659 if(implicitAccesses.size()>1000) return; 660 try { 661 SystemUtil.TemplateLine tl = SystemUtil.getCurrentContext(); 662 String key=tl+":"+scope+":"+name; 663 ImplicitAccessImpl dsc = implicitAccesses.get(key); 664 if(dsc!=null) 665 dsc.inc(); 666 else 667 implicitAccesses.put(key,new ImplicitAccessImpl(scope,name,tl.template,tl.line)); 668 } 669 catch(Throwable t){} 670 } 671 672 @Override 673 public ImplicitAccess[] getImplicitAccesses(int scope, String name) { 674 return implicitAccesses.values().toArray(new ImplicitAccessImpl[implicitAccesses.size()]); 675 } 676 677 public void setOutputLog(DebugOutputLog outputLog) { 678 this.outputLog=outputLog; 679 } 680 681 public DebugTextFragment[] getOutputTextFragments() { 682 return this.outputLog.getFragments(); 683 } 684 685 public Query getOutputText() throws DatabaseException { 686 DebugTextFragment[] fragments = outputLog.getFragments(); 687 int len = fragments==null?0:fragments.length; 688 Query qryOutputLog=new QueryImpl( 689 new Collection.Key[]{ 690 KeyConstants._line 691 ,KeyConstants._template, 692 KeyConstants._text}, 693 len,"query"); 694 695 696 if(len>0) { 697 for(int i=0;i<fragments.length;i++) { 698 qryOutputLog.setAtEL(KeyConstants._line,i+1,fragments[i].line); 699 qryOutputLog.setAtEL(KeyConstants._template,i+1,fragments[i].template); 700 qryOutputLog.setAtEL(KeyConstants._text,i+1,fragments[i].text); 701 } 702 } 703 return qryOutputLog; 704 705 } 706 } 707 708 final class DebugEntryTemplateComparator implements Comparator<DebugEntryTemplate> { 709 710 public int compare(DebugEntryTemplate de1,DebugEntryTemplate de2) { 711 long result = ((de2.getExeTime()+de2.getFileLoadTime())-(de1.getExeTime()+de1.getFileLoadTime())); 712 // we do this addional step to try to avoid ticket RAILO-2076 713 return result>0L?1:(result<0L?-1:0); 714 } 715 } 716 717 final class DebugEntryTemplatePartComparator implements Comparator<DebugEntryTemplatePart> { 718 719 @Override 720 public int compare(DebugEntryTemplatePart de1,DebugEntryTemplatePart de2) { 721 long result=de2.getExeTime()-de1.getExeTime(); 722 // we do this addional step to try to avoid ticket RAILO-2076 723 return result>0L?1:(result<0L?-1:0); 724 } 725 }