package railo.runtime.tag;
import java.io.IOException;
import railo.commons.io.log.Log;
import railo.commons.io.log.LogAndSource;
import railo.commons.io.log.LogUtil;
import railo.commons.lang.StringUtil;
import railo.runtime.PageSource;
import railo.runtime.converter.ConverterException;
import railo.runtime.converter.ScriptConverter;
import railo.runtime.debug.DebugTrace;
import railo.runtime.debug.DebuggerPro;
import railo.runtime.exp.Abort;
import railo.runtime.exp.ApplicationException;
import railo.runtime.exp.PageException;
import railo.runtime.ext.tag.BodyTagImpl;
import railo.runtime.functions.other.Dump;
import railo.runtime.interpreter.VariableInterpreter;
import railo.runtime.op.Caster;
import railo.runtime.type.Struct;
import railo.runtime.type.dt.DateTimeImpl;
import railo.runtime.type.scope.Scope;
import railo.runtime.type.trace.TraceObjectSupport;
public final class Trace extends BodyTagImpl {
private boolean abort=false;
private boolean follow=false;
private String category;
private boolean inline=false;
private String text;
private int type=Log.LEVEL_INFO;
private String var;
private Struct caller;
@Override
public void release() {
super.release();
abort=false;
category=null;
inline=false;
text=null;
type=Log.LEVEL_INFO;
var=null;
caller=null;
follow=false;
}
/**
* @param abort the abort to set
*/
public void setAbort(boolean abort) {
this.abort = abort;
}
public void setFollow(boolean follow) {
this.follow = follow;
}
/**
* @param category the category to set
*/
public void setCategory(String category) {
this.category = category;
}
/**
* @param inline the inline to set
*/
public void setInline(boolean inline) {
this.inline = inline;
}
/**
* @param text the text to set
*/
public void setText(String text) {
this.text = text;
}
/**
* @param type the type to set
* @throws ApplicationException
*/
public void setType(String strType) throws ApplicationException {
strType = strType.toLowerCase().trim();
if("info".equals(strType)) type=Log.LEVEL_INFO;
if("information".equals(strType)) type=Log.LEVEL_INFO;
else if("warn".equals(strType)) type=Log.LEVEL_WARN;
else if("warning".equals(strType)) type=Log.LEVEL_WARN;
else if("error".equals(strType)) type=Log.LEVEL_ERROR;
else if("fatal information".equals(strType)) type=Log.LEVEL_FATAL;
else if("fatal-information".equals(strType)) type=Log.LEVEL_FATAL;
else if("fatal_information".equals(strType)) type=Log.LEVEL_FATAL;
else if("fatalinformation".equals(strType)) type=Log.LEVEL_FATAL;
else if("fatal info".equals(strType)) type=Log.LEVEL_FATAL;
else if("fatal-info".equals(strType)) type=Log.LEVEL_FATAL;
else if("fatal_info".equals(strType)) type=Log.LEVEL_FATAL;
else if("fatalinfo".equals(strType)) type=Log.LEVEL_FATAL;
else if("fatal".equals(strType)) type=Log.LEVEL_FATAL;
else if("debug".equals(strType)) type=Log.LEVEL_DEBUG;
else if("debugging".equals(strType)) type=Log.LEVEL_DEBUG;
else if("debuging".equals(strType)) type=Log.LEVEL_DEBUG;
else throw new ApplicationException("invalid value ["+strType+"] for attribute [type], valid values are [Debug, Information, Warning, Error, Fatal Information]");
}
/**
* @param var the var to set
*/
public void setVar(String var) {
this.var = var;
}
public void setCaller(Struct caller) {
this.caller = caller;
}
/**
* @param var the var to set
*/
public void setVariable(String var) {
this.var = var;
}
@Override
public int doStartTag() {
return EVAL_BODY_INCLUDE;
}
@Override
public int doEndTag() throws PageException {
try {
_doEndTag();
}
catch (IOException e) {}
return EVAL_PAGE;
}
public void _doEndTag() throws IOException, PageException {
PageSource page = pageContext.getCurrentTemplatePageSource();
// var
String varValue=null;
Object value=null,traceValue=null;
if(!StringUtil.isEmpty(var)) {
try {
if(caller instanceof Scope) value=VariableInterpreter.getVariable(pageContext,var,(Scope)caller);
else value = pageContext.getVariable(var);
}
catch (PageException e) {
varValue="(undefined)";
follow=false;
}
if(follow){
//print.o(1);
if(StringUtil.isEmpty(text,true)) text=var;
//print.o(2);
traceValue=TraceObjectSupport.toTraceObject(pageContext.getDebugger(), value, type, category, text);
if(caller instanceof Scope) VariableInterpreter.setVariable(pageContext,var,traceValue,(Scope)caller);
else pageContext.setVariable(var,traceValue);
}
try {
varValue=new ScriptConverter().serialize(value);
}
catch (ConverterException e) {
if(value!=null)varValue="("+Caster.toTypeName(value)+")";
}
}
DebugTrace trace = pageContext.getDebugger().addTrace(type,category,text,page,var,varValue);
DebugTrace[] traces = ((DebuggerPro)pageContext.getDebugger()).getTraces(pageContext);
String total="(1st trace)";
if(traces.length>1) {
long t=0;
for(int i=0;i<traces.length;i++) {
t+=traces[i].getTime();
}
total="("+t+")";
}
boolean hasCat=!StringUtil.isEmpty(trace.getCategory());
boolean hasText=!StringUtil.isEmpty(trace.getText());
boolean hasVar=!StringUtil.isEmpty(var);
// inline
if(inline) {
railo.runtime.format.TimeFormat tf = new railo.runtime.format.TimeFormat(pageContext.getConfig().getLocale());
StringBuffer sb=new StringBuffer();
sb.append("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" bgcolor=\"white\">");
sb.append("<tr>");
//sb.append("<td><img src=\"/CFIDE/debug/images/Error_16x16.gif\" alt=\"Error type\">");
sb.append("<td>");
sb.append("<font color=\"orange\">");
sb.append("<b>");
sb.append(LogUtil.toStringType(trace.getType(),"INFO")+" - ");
sb.append("[CFTRACE "+tf.format(new DateTimeImpl(pageContext.getConfig()), "hh:mm:ss:l")+"]");
sb.append("["+trace.getTime()+" ms "+total+"]");
sb.append("["+trace.getTemplate()+" @ line: "+trace.getLine()+"]");
if(hasCat || hasText)sb.append(" -");
if(hasCat)sb.append(" ["+trace.getCategory()+"]");
if(hasText)sb.append(" <i>"+trace.getText()+" </i>");
sb.append("</b>");
sb.append("</font>");
sb.append("</td>");
sb.append("</tr>");
sb.append("</table>");
pageContext.forceWrite(sb.toString());
if(hasVar)Dump.call(pageContext, value, var);
}
// log
LogAndSource log = pageContext.getConfig().getTraceLogger();
StringBuffer msg=new StringBuffer();
msg.append("["+trace.getTime()+" ms "+total+"] ");
msg.append("["+trace.getTemplate()+" @ line: "+trace.getLine()+"]");
if(hasCat || hasText || hasVar) msg.append("- ");
if(hasCat)msg.append("["+trace.getCategory()+"] ");
if(hasVar)msg.append("["+var+"="+varValue+"] ");
if(hasText)msg.append(" "+trace.getText()+" ");
log.log(trace.getType(), "cftrace", msg.toString());
// abort
if(abort) throw new Abort(Abort.SCOPE_REQUEST);
}
@Override
public void doInitBody() {
}
@Override
public int doAfterBody() {
return SKIP_BODY;
}
/**
* sets if has body or not
* @param hasBody
*/
public void hasBody(boolean hasBody) {
}
}