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()+"&nbsp;</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    }