001    package railo.intergral.fusiondebug.server;
002    
003    import java.util.ArrayList;
004    import java.util.Collections;
005    import java.util.Comparator;
006    import java.util.Iterator;
007    import java.util.List;
008    import java.util.Map.Entry;
009    
010    import railo.commons.lang.StringUtil;
011    import railo.intergral.fusiondebug.server.type.FDVariable;
012    import railo.intergral.fusiondebug.server.util.FDCaster;
013    import railo.runtime.PageContextImpl;
014    import railo.runtime.PageSource;
015    import railo.runtime.exp.PageException;
016    import railo.runtime.op.Caster;
017    import railo.runtime.type.Collection;
018    import railo.runtime.type.KeyImpl;
019    import railo.runtime.type.Scope;
020    import railo.runtime.type.Struct;
021    import railo.runtime.type.scope.ClusterNotSupported;
022    import railo.runtime.type.scope.UndefinedImpl;
023    
024    import com.intergral.fusiondebug.server.FDLanguageException;
025    import com.intergral.fusiondebug.server.IFDStackFrame;
026    import com.intergral.fusiondebug.server.IFDThread;
027    import com.intergral.fusiondebug.server.IFDVariable;
028    
029    public class FDStackFrameImpl implements IFDStackFrame {
030    
031    
032            private static final Collection.Key CALLER = KeyImpl.intern("caller");
033            
034            private static final int[] SCOPES_AS_INT = new int[]{
035                    Scope.SCOPE_VARIABLES,Scope.SCOPE_CGI,Scope.SCOPE_URL,Scope.SCOPE_FORM,
036                    Scope.SCOPE_COOKIE,Scope.SCOPE_CLIENT,Scope.SCOPE_APPLICATION,Scope.SCOPE_CALLER,
037                    Scope.SCOPE_CLUSTER,Scope.SCOPE_REQUEST,Scope.SCOPE_SERVER,Scope.SCOPE_SESSION
038            };
039            private static final String[] SCOPES_AS_STRING = new String[]{
040                    "variables","cgi","url","form",
041                    "cookie","client","application","caller",
042                    "cluster","request","server","session"
043            };
044     
045            private PageContextImpl pc;
046            private FDThreadImpl thread;
047    
048            //private StackTraceElement trace;
049    
050            private PageSource ps;
051    
052            private int line;
053    
054            private static Comparator comparator=new FDVariableComparator();
055    
056            public FDStackFrameImpl(FDThreadImpl thread,PageContextImpl pc, StackTraceElement trace, PageSource ps){
057                    this(thread, pc, ps, trace.getLineNumber());
058            } 
059            public FDStackFrameImpl(FDThreadImpl thread,PageContextImpl pc, PageSource ps, int line){
060                    this.thread=thread;
061                    this.pc=pc;
062                    this.line=line;
063                    this.ps=ps;
064            } 
065            
066            /**
067             * @see com.intergral.fusiondebug.server.IFDStackFrame#evaluate(java.lang.String)
068             */
069            public IFDVariable evaluate(String expression) throws FDLanguageException {
070                    try {
071                            return new FDVariable(this,expression,FDCaster.toFDValue(this,pc.evaluate(expression)));
072                    } 
073                    catch (PageException e) {
074                            throw new FDLanguageException(e);
075                    }
076            }
077    
078            /**
079             * @see com.intergral.fusiondebug.server.IFDStackFrame#getExecutionUnitName()
080             */
081            public String getExecutionUnitName() {
082                    return ps.getClassName();
083            }
084    
085            /**
086             * @see com.intergral.fusiondebug.server.IFDStackFrame#getExecutionUnitPackage()
087             */
088            public String getExecutionUnitPackage() {
089                    return ps.getPackageName();
090            }
091    
092            /**
093             * @see com.intergral.fusiondebug.server.IFDStackFrame#getLineNumber()
094             */
095            public int getLineNumber() {
096                    return line;
097                    
098            }
099            
100            /**
101             * @see com.intergral.fusiondebug.server.IFDStackFrame#getSourceFileName()
102             */
103            public String getSourceFileName() {
104                    return ps.getFileName();
105            }
106    
107            /**
108             * @see com.intergral.fusiondebug.server.IFDStackFrame#getSourceFilePath()
109             */
110            public String getSourceFilePath() {
111                    String name = getSourceFileName();
112                    String path=ps.getDisplayPath();
113                    if(StringUtil.endsWithIgnoreCase(path, name))
114                            path=path.substring(0,path.length()-name.length());
115                    return path;
116            }
117    
118            /**
119             * @see com.intergral.fusiondebug.server.IFDStackFrame#getThread()
120             */
121            public IFDThread getThread() {
122                    return thread;
123            }
124    
125            /**
126             * @see com.intergral.fusiondebug.server.IFDStackFrame#getScopeNames()
127             */
128            public List getScopeNames() {
129                    List implScopes = ((UndefinedImpl) pc.undefinedScope()).getScopeNames();
130                    for(int i=0;i<SCOPES_AS_INT.length;i++){
131                            if(!implScopes.contains(SCOPES_AS_STRING[i]) && enabled(pc,SCOPES_AS_INT[i]))
132                                    implScopes.add(SCOPES_AS_STRING[i]);
133                    }
134                    return implScopes;
135            }
136            public static List testScopeNames(PageContextImpl pc) {
137                    return new FDStackFrameImpl(null,pc,null,null).getScopeNames();
138            }
139            
140            private static boolean enabled(PageContextImpl pc,int scope) {
141                    if(Scope.SCOPE_CLIENT==scope){
142                            return pc.getApplicationContext().isSetClientManagement();
143                    }
144                    if(Scope.SCOPE_SESSION==scope){
145                            return pc.getApplicationContext().isSetSessionManagement();
146                    }
147                    if(Scope.SCOPE_CALLER==scope){
148                            return pc.undefinedScope().get(CALLER,null) instanceof Struct;
149                    }
150                    if(Scope.SCOPE_CLUSTER==scope){
151                            try {
152                                    return !(pc.clusterScope() instanceof ClusterNotSupported);
153                            } catch (PageException e) {
154                                    //e.printStackTrace();
155                                    return false;
156                            }
157                    }
158                    return true;
159            }
160    
161            /**
162             * @see com.intergral.fusiondebug.server.IFDStackFrame#getVariables()
163             */
164            public List getVariables() {
165                    Iterator it = getScopeNames().iterator();
166                    List list=new ArrayList();
167                    
168                    while(it.hasNext()){
169                            try {
170                                    getVariables(this,pc,list, (String)it.next());
171                            } 
172                            catch (FDLanguageException e) {e.printStackTrace();}
173                    }
174                    return sort(list);
175            }
176    
177            public static List testVariables(PageContextImpl pc) {
178                    return new FDStackFrameImpl(null,pc,null,null).getVariables();
179            }
180            
181    
182            /**
183             * @see com.intergral.fusiondebug.server.IFDStackFrame#getVariables(java.lang.String)
184             */
185            public List getVariables(String strScope) throws FDLanguageException {
186                    return sort(getVariables(this,pc,new ArrayList(), strScope));
187            }
188            
189    
190            public static List testVariables(PageContextImpl pc,String strScope) throws FDLanguageException {
191                    return new FDStackFrameImpl(null,pc,null,null).getVariables(strScope);
192            }
193            
194            private static List getVariables(FDStackFrameImpl frame,PageContextImpl pc,List list,String strScope) throws FDLanguageException {
195                    Scope scope;
196                    try {
197                            scope = pc.scope(strScope, null);
198                            if(scope!=null) return copyValues(frame,list,scope);
199                            
200                            Object value=pc.undefinedScope().get(strScope,null);
201                            if(value!=null) {
202                                    if(value instanceof Struct)return copyValues(frame,new ArrayList(),(Struct)value);
203                                    throw new FDLanguageException("["+strScope+"] is not of type scope, type is ["+Caster.toTypeName(value)+"]");
204                            }
205                            throw new FDLanguageException("["+strScope+"] does not exist in the current context");
206                    } 
207                    catch (PageException e) {
208                            throw new FDLanguageException(e);
209                    }
210            }
211    
212            /**
213             * copy all data from given struct to given list and translate it to a FDValue
214             * @param to list to fill with values
215             * @param from struct to read values from
216             * @return the given list
217             */
218            private static List copyValues(FDStackFrameImpl frame,List to,Struct from) {
219                    Iterator it = from.entrySet().iterator();
220                    Entry entry;
221                    while(it.hasNext()){
222                            entry=(Entry) it.next();
223                            to.add(new FDVariable(frame,(String)entry.getKey(),FDCaster.toFDValue(frame,entry.getValue())));
224                    }
225                    return to;
226            }
227    
228            private static List sort(List list) {
229                    Collections.sort(list,comparator);
230                    return list;
231            }
232    
233            /**
234             * @see com.intergral.fusiondebug.server.IFDStackFrame#getFrameInformation()
235             */
236            public String getFrameInformation() {
237                    return ps.getFullRealpath();
238            }
239            
240            public String toString(){
241                    return "path:"+getSourceFilePath()+";name:"+getSourceFileName()+";unit-pack:"+getExecutionUnitPackage()+";unit-name:"+getExecutionUnitName()+";line:"+getLineNumber();
242            }
243    
244    
245    }
246    
247    class FDVariableComparator implements Comparator {
248    
249            /**
250             * @see java.util.Comparator#compare(T, T)
251             */
252            public int compare(Object o1, Object o2) {
253                    return ((FDVariable)o1).getName().compareToIgnoreCase(((FDVariable)o2).getName());
254            }
255    }