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