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