001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.intergral.fusiondebug.server;
020
021import java.util.ArrayList;
022import java.util.List;
023
024import lucee.commons.io.SystemUtil;
025import lucee.commons.io.log.Log;
026import lucee.commons.io.res.Resource;
027import lucee.commons.io.res.util.ResourceUtil;
028import lucee.runtime.CFMLFactoryImpl;
029import lucee.runtime.PageContext;
030import lucee.runtime.PageContextImpl;
031import lucee.runtime.PageSource;
032import lucee.runtime.config.ConfigImpl;
033import lucee.transformer.bytecode.util.ASMUtil;
034
035import com.intergral.fusiondebug.server.IFDController;
036import com.intergral.fusiondebug.server.IFDStackFrame;
037import com.intergral.fusiondebug.server.IFDThread;
038
039public class FDThreadImpl implements IFDThread {
040        
041        
042        private PageContextImpl pc;
043        private String name;
044        private FDControllerImpl engine;
045        //private CFMLFactoryImpl factory;
046
047        
048        public FDThreadImpl(FDControllerImpl engine,CFMLFactoryImpl factory, String name, PageContextImpl pc) {
049                this.engine=engine;
050                //this.factory=factory;
051                this.name=name;
052                this.pc=pc;
053        }
054
055        @Override
056        public String getName() {
057                return name+":"+pc.getCFID();
058        }
059
060        @Override
061        public int id() {
062                return pc.getId();
063        }
064        
065        public static int id(PageContext pc) {
066                return pc.getId();
067        }
068
069        @Override
070        public void stop() {
071                Log log = ((ConfigImpl)pc.getConfig()).getLog("application");
072        SystemUtil.stop(pc,log);
073        }
074        
075        @Override
076        public Thread getThread() {
077                return pc.getThread();
078        }
079
080        @Override
081        public String getOutputBuffer() {
082                return pc.getRootOut().toString();
083        }
084
085
086        public List getStackFrames() {
087                return getStack();
088        }
089        public List getStack() {
090                List stack = pc.getPageSourceList();
091                
092                StackTraceElement[] traces = pc.getThread().getStackTrace();
093                String template="";
094                StackTraceElement trace=null;
095                ArrayList list=new ArrayList();
096                Resource res;
097                PageSource ps;
098                int index=stack.size();
099                for(int i=traces.length-1;i>=0;i--) {
100                        trace=traces[i];
101                        ps=null;
102                        if(trace.getLineNumber()<=0) continue;
103                        template=trace.getFileName();
104                        if(template==null || ResourceUtil.getExtension(template,"").equals("java")) continue;
105                        
106                        if(index>0)ps=(PageSource) stack.get(--index);
107                        if(ps==null || !isEqual(ps,trace)){
108                                ps=toPageSource(pc,template);
109                        }
110                        FDStackFrameImpl frame = new FDStackFrameImpl(this,pc,trace,ps);
111                        if(ASMUtil.isOverfowMethod(trace.getMethodName())) list.set(0,frame);
112                        else list.add(0,frame);
113                }
114                return list;
115        }
116        
117        public IFDStackFrame getTopStack(){
118                return getTopStackFrame();
119        }
120        
121        @Override
122    public IFDStackFrame getTopStackFrame(){
123                PageSource ps = pc.getCurrentPageSource();
124                
125                StackTraceElement[] traces = pc.getThread().getStackTrace();
126                String template="";
127                StackTraceElement trace=null;
128                
129                for(int i=0;i<traces.length;i++) {
130                        trace=traces[i];
131                        if(trace.getLineNumber()<=0) continue;
132                        template=trace.getFileName();
133                        if(template==null || ResourceUtil.getExtension(template,"").equals("java")) continue;
134                        
135                        if(ps==null || !isEqual(ps,trace)){
136                                ps=toPageSource(pc,template);
137                        }
138                        break;
139                }
140                return new FDStackFrameImpl(this,pc,trace,ps);  
141        }
142        
143        private PageSource toPageSource(PageContextImpl pc2, String template) {
144                Resource res = ResourceUtil.toResourceNotExisting(pc, template);
145                return pc.toPageSource(res, null);
146        }
147
148        private boolean isEqual(PageSource ps, StackTraceElement trace) {
149                // class name do not match
150                if(!ps.getFullClassName().equals(trace.getClassName())) return false;
151                // filename to not match
152                if(!ps.getResource().getAbsolutePath().equals(trace.getFileName())) return false;
153                
154                return true;
155        }
156
157        /**
158         * @return the engine
159         */
160        public IFDController getController() {
161                return engine;
162        }
163
164
165}