001 package railo.runtime.tag; 002 003 import java.io.IOException; 004 005 import railo.commons.io.log.Log; 006 import railo.commons.io.log.LogAndSource; 007 import railo.commons.io.log.LogUtil; 008 import railo.commons.lang.StringUtil; 009 import railo.runtime.PageSource; 010 import railo.runtime.converter.ConverterException; 011 import railo.runtime.converter.ScriptConverter; 012 import railo.runtime.debug.DebugTrace; 013 import railo.runtime.exp.Abort; 014 import railo.runtime.exp.ApplicationException; 015 import railo.runtime.exp.PageException; 016 import railo.runtime.ext.tag.BodyTagImpl; 017 import railo.runtime.functions.other.Dump; 018 import railo.runtime.interpreter.VariableInterpreter; 019 import railo.runtime.op.Caster; 020 import railo.runtime.type.Scope; 021 import railo.runtime.type.Struct; 022 import railo.runtime.type.dt.DateTimeImpl; 023 import railo.runtime.type.trace.TraceObjectSupport; 024 025 public final class Trace extends BodyTagImpl { 026 027 private boolean abort=false; 028 private boolean follow=false; 029 private String category; 030 private boolean inline=false; 031 private String text; 032 private int type=Log.LEVEL_INFO; 033 private String var; 034 private Struct caller; 035 036 037 /** 038 * 039 * @see railo.runtime.ext.tag.TagImpl#release() 040 */ 041 public void release() { 042 super.release(); 043 abort=false; 044 category=null; 045 inline=false; 046 text=null; 047 type=Log.LEVEL_INFO; 048 var=null; 049 caller=null; 050 follow=false; 051 } 052 053 /** 054 * @param abort the abort to set 055 */ 056 public void setAbort(boolean abort) { 057 this.abort = abort; 058 } 059 public void setFollow(boolean follow) { 060 this.follow = follow; 061 } 062 063 /** 064 * @param category the category to set 065 */ 066 public void setCategory(String category) { 067 this.category = category; 068 } 069 070 /** 071 * @param inline the inline to set 072 */ 073 public void setInline(boolean inline) { 074 this.inline = inline; 075 } 076 077 /** 078 * @param text the text to set 079 */ 080 public void setText(String text) { 081 this.text = text; 082 } 083 084 /** 085 * @param type the type to set 086 * @throws ApplicationException 087 */ 088 public void setType(String strType) throws ApplicationException { 089 strType = strType.toLowerCase().trim(); 090 if("info".equals(strType)) type=Log.LEVEL_INFO; 091 if("information".equals(strType)) type=Log.LEVEL_INFO; 092 else if("warn".equals(strType)) type=Log.LEVEL_WARN; 093 else if("warning".equals(strType)) type=Log.LEVEL_WARN; 094 else if("error".equals(strType)) type=Log.LEVEL_ERROR; 095 else if("fatal information".equals(strType)) type=Log.LEVEL_FATAL; 096 else if("fatal-information".equals(strType)) type=Log.LEVEL_FATAL; 097 else if("fatal_information".equals(strType)) type=Log.LEVEL_FATAL; 098 else if("fatalinformation".equals(strType)) type=Log.LEVEL_FATAL; 099 else if("fatal info".equals(strType)) type=Log.LEVEL_FATAL; 100 else if("fatal-info".equals(strType)) type=Log.LEVEL_FATAL; 101 else if("fatal_info".equals(strType)) type=Log.LEVEL_FATAL; 102 else if("fatalinfo".equals(strType)) type=Log.LEVEL_FATAL; 103 else if("fatal".equals(strType)) type=Log.LEVEL_FATAL; 104 else if("debug".equals(strType)) type=Log.LEVEL_DEBUG; 105 else if("debugging".equals(strType)) type=Log.LEVEL_DEBUG; 106 else if("debuging".equals(strType)) type=Log.LEVEL_DEBUG; 107 else throw new ApplicationException("invalid value ["+strType+"] for attribute [type], valid values are [Debug, Information, Warning, Error, Fatal Information]"); 108 } 109 110 /** 111 * @param var the var to set 112 */ 113 public void setVar(String var) { 114 this.var = var; 115 } 116 117 public void setCaller(Struct caller) { 118 this.caller = caller; 119 } 120 121 /** 122 * @param var the var to set 123 */ 124 public void setVariable(String var) { 125 this.var = var; 126 } 127 128 /** 129 * 130 * @see railo.runtime.ext.tag.TagImpl#doStartTag() 131 */ 132 public int doStartTag() { 133 return EVAL_BODY_INCLUDE; 134 } 135 136 137 /** 138 * 139 * @throws PageException 140 * @throws IOException 141 * @see railo.runtime.ext.tag.TagImpl#doEndTag() 142 */ 143 public int doEndTag() throws PageException { 144 try { 145 _doEndTag(); 146 } 147 catch (IOException e) {} 148 return EVAL_PAGE; 149 } 150 151 public void _doEndTag() throws IOException, PageException { 152 153 PageSource page = pageContext.getCurrentTemplatePageSource(); 154 155 // var 156 String varValue=null; 157 Object value=null,traceValue=null; 158 if(!StringUtil.isEmpty(var)) { 159 160 try { 161 if(caller instanceof Scope) value=VariableInterpreter.getVariable(pageContext,var,(Scope)caller); 162 else value = pageContext.getVariable(var); 163 } 164 catch (PageException e) { 165 varValue="(undefined)"; 166 follow=false; 167 } 168 169 if(follow){ 170 //print.o(1); 171 if(StringUtil.isEmpty(text,true)) text=var; 172 //print.o(2); 173 traceValue=TraceObjectSupport.toTraceObject(pageContext.getDebugger(), value, type, category, text); 174 175 if(caller instanceof Scope) VariableInterpreter.setVariable(pageContext,var,traceValue,(Scope)caller); 176 else pageContext.setVariable(var,traceValue); 177 } 178 179 try { 180 varValue=new ScriptConverter().serialize(value); 181 } 182 catch (ConverterException e) { 183 if(value!=null)varValue="("+Caster.toTypeName(value)+")"; 184 } 185 186 187 188 } 189 190 DebugTrace trace = pageContext.getDebugger().addTrace(type,category,text,page,var,varValue); 191 DebugTrace[] traces = pageContext.getDebugger().getTraces(); 192 193 String total="(1st trace)"; 194 if(traces.length>1) { 195 long t=0; 196 for(int i=0;i<traces.length;i++) { 197 t+=traces[i].getTime(); 198 } 199 total="("+t+")"; 200 } 201 202 boolean hasCat=!StringUtil.isEmpty(trace.getCategory()); 203 boolean hasText=!StringUtil.isEmpty(trace.getText()); 204 boolean hasVar=!StringUtil.isEmpty(var); 205 206 // inline 207 if(inline) { 208 railo.runtime.format.TimeFormat tf = new railo.runtime.format.TimeFormat(pageContext.getConfig().getLocale()); 209 StringBuffer sb=new StringBuffer(); 210 sb.append("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" bgcolor=\"white\">"); 211 sb.append("<tr>"); 212 //sb.append("<td><img src=\"/CFIDE/debug/images/Error_16x16.gif\" alt=\"Error type\">"); 213 sb.append("<td>"); 214 sb.append("<font color=\"orange\">"); 215 sb.append("<b>"); 216 sb.append(LogUtil.toStringType(trace.getType(),"INFO")+" - "); 217 sb.append("[CFTRACE "+tf.format(new DateTimeImpl(pageContext.getConfig()), "hh:mm:ss:l")+"]"); 218 sb.append("["+trace.getTime()+" ms "+total+"]"); 219 sb.append("["+trace.getTemplate()+" @ line: "+trace.getLine()+"]"); 220 if(hasCat || hasText)sb.append(" -"); 221 if(hasCat)sb.append(" ["+trace.getCategory()+"]"); 222 if(hasText)sb.append(" <i>"+trace.getText()+" </i>"); 223 sb.append("</b>"); 224 sb.append("</font>"); 225 sb.append("</td>"); 226 sb.append("</tr>"); 227 sb.append("</table>"); 228 pageContext.forceWrite(sb.toString()); 229 230 if(hasVar)Dump.call(pageContext, value, var); 231 232 } 233 234 // log 235 LogAndSource log = pageContext.getConfig().getTraceLogger(); 236 StringBuffer msg=new StringBuffer(); 237 msg.append("["+trace.getTime()+" ms "+total+"] "); 238 msg.append("["+trace.getTemplate()+" @ line: "+trace.getLine()+"]"); 239 if(hasCat || hasText || hasVar) msg.append("- "); 240 if(hasCat)msg.append("["+trace.getCategory()+"] "); 241 if(hasVar)msg.append("["+var+"="+varValue+"] "); 242 if(hasText)msg.append(" "+trace.getText()+" "); 243 log.log(trace.getType(), "cftrace", msg.toString()); 244 245 // abort 246 if(abort) throw new Abort(Abort.SCOPE_REQUEST); 247 248 } 249 250 /** 251 * @see javax.servlet.jsp.tagext.BodyTag#doInitBody() 252 */ 253 public void doInitBody() { 254 255 } 256 257 /** 258 * @see javax.servlet.jsp.tagext.BodyTag#doAfterBody() 259 */ 260 public int doAfterBody() { 261 return SKIP_BODY; 262 } 263 264 /** 265 * sets if has body or not 266 * @param hasBody 267 */ 268 public void hasBody(boolean hasBody) { 269 270 } 271 }