/* * Copyright (C) 2000 - 2012 TagServlet Ltd * * This file is part of Open BlueDragon (OpenBD) CFML Server Engine. * * OpenBD is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * Free Software Foundation,version 3. * * OpenBD is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenBD. If not, see http://www.gnu.org/licenses/ * * Additional permission under GNU GPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or combining * it with any of the JARS listed in the README.txt (or a modified version of * (that library), containing parts covered by the terms of that JAR, the * licensors of this Program grant you additional permission to convey the * resulting work. * README.txt @ http://www.openbluedragon.org/license/README.txt * * http://openbd.org/ * $Id: fullRecorder.java 2374 2013-06-10 22:14:24Z alan $ */ package com.naryx.tagfusion.util; /** * This class does nothing with the events triggered for * debugging purposes. Used when debugging is not enabled. */ import java.io.CharArrayWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.Map; import org.bson.Document; import com.mongodb.client.MongoCollection; import com.naryx.tagfusion.cfm.engine.cfData; import com.naryx.tagfusion.cfm.engine.cfEngine; import com.naryx.tagfusion.cfm.engine.cfSession; import com.naryx.tagfusion.cfm.engine.cfStructData; import com.naryx.tagfusion.cfm.engine.cfmRunTimeException; import com.naryx.tagfusion.cfm.file.cfFile; import com.naryx.tagfusion.cfm.sql.cfSQLQueryData; import com.naryx.tagfusion.cfm.sql.preparedData; import com.naryx.tagfusion.cfm.sql.resultSetHolder; import com.naryx.tagfusion.cfm.tag.cfDUMP; import com.naryx.tagfusion.cfm.tag.cfTag; public class fullRecorder implements debugRecorder { public static final String DEFAULT_ENABLED = "false"; public static final String DEFAULT_EXEC_TIME_SHOW = "false"; public static final String DEFAULT_EXEC_TIME_HIGHLIGHT = "250"; public static final String DEFAULT_EXCEPTIONS_SHOW = "false"; public static final String DEFAULT_DATABASE_SHOW = "false"; public static final String DEFAULT_TRACEPOINTS_SHOW = "false"; public static final String DEFAULT_TIMER_SHOW = "false"; public static final String DEFAULT_VARIABLES_SHOW = "false"; public static final String DEFAULT_VARIABLES = "true"; public static final String DEFAULT_IP_ADDRESSES = ""; private debugQuery dbgQuery; private debugExceptions dbgExceptions; // the exceptions thrown in the request private debugExecution dbgExecution; private debugStoredProc dbgStoredProcs; private List<String> tracepoints; private List<String> timer; private boolean show; // whether to display the output. Set by CFSETTING private boolean showDB; // whether to display the db activity private long reqStart; private long reqEnd; public fullRecorder(){ dbgExecution = new debugExecution(); dbgExceptions = new debugExceptions(); dbgQuery = new debugQuery(); dbgStoredProcs = new debugStoredProc(); tracepoints = new ArrayList<String>(); timer = new ArrayList<String>(); show = true; showDB = getConfigBoolean( "database.show", Boolean.valueOf( DEFAULT_DATABASE_SHOW ).booleanValue() ); } private fullRecorder( fullRecorder _recorder ){ dbgExecution = _recorder.dbgExecution.copy(); dbgExceptions = _recorder.dbgExceptions; dbgQuery = _recorder.dbgQuery; dbgStoredProcs = _recorder.dbgStoredProcs; tracepoints = _recorder.tracepoints; timer = _recorder.timer; show = _recorder.show; showDB = _recorder.showDB; reqStart = _recorder.reqStart; } public debugRecorder copy(){ return new fullRecorder( this ); } public void startRequest(){ reqStart = System.currentTimeMillis(); } public void endRequest(){ reqEnd = System.currentTimeMillis(); } public void setShow( boolean _show ){ show = _show; } public boolean getShow(){ return show; } /** * This is used by a query to deterine whether it should * record debug data (in conjunction with it's own debug attribute) */ public boolean getShowDBActivity(){ return showDB; } public void startFile( cfFile thisFile ){ dbgExecution.startFile( thisFile ); } public void endFile( cfFile thisFile ){ dbgExecution.endFile( thisFile ); } public void queryRan( String _template, String _qname, cfSQLQueryData _query, List<preparedData> _qp ){ dbgQuery.addQuery( _qname, _template, _query, _qp ); } public void updateRan( String _template, String _datasrc, String _sql ){ dbgQuery.addUpdate( _template, _datasrc, _sql ); } public void insertRan( String _template, String _datasrc, String _sql ){ dbgQuery.addInsert( _template, _datasrc, _sql ); } public void exceptionThrown( cfmRunTimeException exception, cfFile originF, cfTag originT ){ dbgExceptions.add( exception, originF, originT ); } public void storedProcRan( String _template, String _datasrc, String _procName, long _execTime, List<preparedData> _params, List<resultSetHolder> _results ){ dbgStoredProcs.add( _template, _datasrc, _procName, _execTime, _params, _results ); } public void recordTracepoint( String tracePoint ) { tracepoints.add( tracePoint ); } public void recordTimer( String _timing ) { timer.add( _timing ); } public void dump( cfSession session ){ // Don't dump the debug output if the request comes from the admin if ( !show ) return; session.setProcessingCfOutput( true ); endRequest(); long debugRenderStart = System.currentTimeMillis(); boolean isWindowsUser = session.isWindowsOrMacUser(); String fontSize = ( isWindowsUser ? "small" : "medium" ); String hdrFontSize = ( isWindowsUser ? "medium" : "large" ); // dump a bunch of end tags to ensure that any unclosed elements don't // disrupt the format of the debug output session.write( "</td></td></td></th></th></th></tr></tr></tr></table></table>" ); session.write( "</table></a></abbrev></acronym></address></applet></au></b></banner>" ); session.write( "</big></blink></blockquote></bq></caption></center></cite></code></comment>"); session.write( "</del></dfn></dir></div></div></dl></em></fig></fn></font></form></frame>"); session.write( "</frameset></h1></h2></h3></h4></h5></h6></head></i></ins></kbd></listing>" ); session.write( "</map></marquee></menu></multicol></nobr></noframes></noscript></note></ol>" ); session.write( "</p></param></person></plaintext></pre></q></s></samp></script></select>" ); session.write( "</small></strike></strong></sub></sup></table></td></textarea></th></title>" ); session.write( "</tr></tt></u></ul></var></wbr></xmp>" ); session.write( "<style type=\"text/css\">\n" ); session.write( ".debug\n{" ); session.write( " color:black;\n" ); session.write( " background-color:white;\n" ); session.write( " font-family:\"Times New Roman\", Times, serif;\n" ); session.write( " font-size: " + fontSize + "\n}\n\n" ); session.write( ".debughdr\n{\n" ); session.write( " color:black;\n" ); session.write( " background-color:white;\n" ); session.write( " font-family:\"Times New Roman\", Times, serif;\n" ); session.write( " font-size: " + hdrFontSize + ";\n}\n\n" ); session.write( "a.debuglink {color:blue; background-color:white }\n" ); session.write( "</style>\n<div id='openbddebug'>" ); dumpDebugInfo( session ); if ( getConfigBoolean( "executiontimes.show", Boolean.valueOf( DEFAULT_EXEC_TIME_SHOW ).booleanValue() ) ) dumpExecution( session ); // if there are queries to show if ( dbgQuery.hasQueries() ){ dbgQuery.dump( session ); } if ( dbgStoredProcs.hasQueries() ){ dbgStoredProcs.dump( session ); } // if exception reporting if ( getConfigBoolean( "exceptions.show", Boolean.valueOf( DEFAULT_EXCEPTIONS_SHOW ).booleanValue() ) ) dumpExceptions( session ); // if tracepoints enabled if ( getConfigBoolean( "tracepoints.show", Boolean.valueOf( DEFAULT_TRACEPOINTS_SHOW ).booleanValue() ) ) dumpTracepoints( session ); // if timer enabled if ( getConfigBoolean( "timer.show", Boolean.valueOf( DEFAULT_TIMER_SHOW ).booleanValue() ) ) dumpTimer( session ); // if scope dumping enabled if ( getConfigBoolean( "variables.show", Boolean.valueOf( DEFAULT_VARIABLES_SHOW ).booleanValue() ) ) dumpScopeVars( session ); long debugRenderEnd = System.currentTimeMillis(); session.write( "<p style=\"font-style: italic;\">Debug Rendering Time: " + (debugRenderEnd-debugRenderStart) + " ms</p></div>" ); } //--[ methods for getting config values // returns a boolean value from the server.debugoutput structure within the config public static boolean getConfigBoolean( String _k, boolean _default ){ return cfEngine.getConfig().getBoolean( "server.debugoutput." + _k, _default ); } // returns an integer value from the server.debugoutput structure within the config private static int getConfigInt( String _k, int _default ) { return cfEngine.getConfig().getInt( "server.debugoutput." + _k, _default ); } //--[ Dump methods private static void dumpDebugInfo( cfSession session ){ (new debugInfo() ).dump( session ); } private void dumpTracepoints( cfSession session ) { if ( tracepoints.size() > 0 ) { session.write( "<hr/><p><b><div class=\"debughdr\">Trace Points</div></b></p>\n<p>\n" ); session.write( "<ul>" ); Iterator<String> iter = tracepoints.iterator(); while ( iter.hasNext() ) { session.write( "<li>" + iter.next() ); } session.write( "</ul>" ); } } private void dumpTimer( cfSession session ) { if ( timer.size() > 0 ) { session.write( "<hr/><p><b><div class=\"debughdr\">CFTimer timings</div></b></p>\n<p>\n" ); session.write( "<ul>" ); Iterator<String> iter = timer.iterator(); while ( iter.hasNext() ) { session.write( "<li>" + iter.next() ); } session.write( "</ul>" ); } } private void dumpExecution( cfSession session ){ dbgExecution.dump( session, (reqEnd-reqStart), getConfigInt( "executiontimes.highlight", Integer.parseInt( DEFAULT_EXEC_TIME_HIGHLIGHT ) ) ); }// dumpExecution() private void dumpExceptions( cfSession session ){ dbgExceptions.dump( session ); } private void dumpScopeVars( cfSession session ){ CharArrayWriter outChar = new CharArrayWriter( 1024 ); PrintWriter out = new PrintWriter( outChar ); cfDUMP.writeDumpStyles( session, out ); out.write( "<hr/><p><b><div class=\"debughdr\">Scope Variables</div></b></p>\n<p>\n" ); Map<String, cfStructData> hT = session.getDataStore(); Enumeration<String> E = new com.nary.util.StringSortedEnumeration( Collections.enumeration( hT.keySet() ) ); while ( E.hasMoreElements() ){ String key = E.nextElement(); boolean dumpScope = getConfigBoolean( "variables." + key, Boolean.valueOf( DEFAULT_VARIABLES ).booleanValue() ); if ( dumpScope ){ cfStructData data = hT.get( key ); out.write( "<p><div class=\"debughdr\">" ); out.write( key ); out.write( "</div></b></p>\n<p>\n" ); out.write( "<table width='100%' cellspacing='0' cellpadding='1' border='1' bgcolor='white'>" ); if ( key.equalsIgnoreCase("url") && cfEngine.isFormUrlScopeCombined() ) out.write( "<tr><td><i>see [form] scope</i></td></tr>" ); else data.dump( out ); out.write( "</table>\n</p>" ); } } out.flush(); session.write( outChar.toString() ); }// dumpScopeVars() @Override public void execOnStart(cfData sqlData) {} @Override public void execOnEnd(cfData sqlData) {} @Override public void execStoredProc(String datasourceName, String callString, String procName, long execTime) { } public void execMongo( MongoCollection<Document> col, String action, Document qry, long execTime ){} }