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.transformer.bytecode; 020 021import java.util.Iterator; 022import java.util.List; 023import java.util.Stack; 024 025import lucee.commons.lang.StringUtil; 026import lucee.runtime.PageSource; 027import lucee.transformer.Context; 028import lucee.transformer.bytecode.literal.LitString; 029import lucee.transformer.bytecode.visitor.OnFinally; 030 031import org.objectweb.asm.ClassWriter; 032import org.objectweb.asm.commons.GeneratorAdapter; 033import org.objectweb.asm.commons.Method; 034 035public class BytecodeContext implements Context { 036 037 038 private ClassWriter classWriter; 039 private GeneratorAdapter adapter; 040 private String className; 041 private List<LitString> keys; 042 private int count=0; 043 private Method method; 044 private boolean doSubFunctions=true; 045 private BytecodeContext staticConstr; 046 private BytecodeContext constr; 047 private final boolean suppressWSbeforeArg; 048 private final boolean output; 049 050 private static long _id=0; 051 private synchronized static String id() { 052 if(_id<0)_id=0; 053 return StringUtil.addZeros(++_id,4); 054 } 055 056 private String id=id(); 057 private Page page; 058 private PageSource source; 059 060 public BytecodeContext(PageSource source,BytecodeContext statConstr,BytecodeContext constr,Page page,List<LitString> keys,ClassWriter classWriter,String className, GeneratorAdapter adapter, 061 Method method,boolean writeLog, boolean suppressWSbeforeArg, boolean output) { 062 this.classWriter = classWriter; 063 this.className = className; 064 this.writeLog = writeLog; 065 this.adapter = adapter; 066 this.keys = keys; 067 this.method=method; 068 this.staticConstr=statConstr; 069 this.constr=constr; 070 this.page=page; 071 this.suppressWSbeforeArg=suppressWSbeforeArg; 072 this.output=output; 073 if(source!=null)this.source=source; 074 else if(constr!=null)this.source=constr.source; 075 else if(statConstr!=null)this.source=statConstr.source; 076 } 077 078 public BytecodeContext(BytecodeContext statConstr,BytecodeContext constr,List<LitString> keys,BytecodeContext bc, GeneratorAdapter adapter,Method method) { 079 this.classWriter = bc.getClassWriter(); 080 this.className = bc.getClassName(); 081 this.writeLog = bc.writeLog(); 082 083 this.adapter = adapter; 084 this.keys = keys; 085 this.method=method; 086 this.staticConstr=statConstr; 087 this.constr=constr; 088 this.page=bc.getPage(); 089 this.suppressWSbeforeArg=bc.suppressWSbeforeArg; 090 this.output=bc.output; 091 this.source=bc.source; 092 } 093 094 /** 095 * @return the id 096 */ 097 public String getId() { 098 return id; 099 } 100 101 /** 102 * @return the count 103 */ 104 public int getCount() { 105 return count; 106 } 107 108 /** 109 * @param count the count to set 110 */ 111 public int incCount() { 112 return ++this.count; 113 } 114 public void resetCount() { 115 this.count=0; 116 } 117 /** 118 * @return the adapter 119 */ 120 public GeneratorAdapter getAdapter() { 121 return adapter; 122 } 123 /** 124 * @param adapter the adapter to set 125 */ 126 public void setAdapter(BytecodeContext bc) { 127 this.adapter = bc.getAdapter(); 128 } 129 /** 130 * @return the classWriter 131 */ 132 public ClassWriter getClassWriter() { 133 return classWriter; 134 } 135 /** 136 * @param classWriter the classWriter to set 137 */ 138 public void setClassWriter(ClassWriter classWriter) { 139 this.classWriter = classWriter; 140 } 141 /** 142 * @return the className 143 */ 144 public String getClassName() { 145 return className; 146 } 147 /** 148 * @param className the className to set 149 */ 150 public void setClassName(String className) { 151 this.className = className; 152 } 153 154 public synchronized int registerKey(LitString lit) { 155 int index = keys.indexOf(lit); 156 if(index!=-1)return index;// calls the toString method of litString 157 158 keys.add(lit); 159 160 return keys.size()-1; 161 } 162 163 public List<LitString> getKeys() { 164 return keys; 165 } 166 167 168 Stack<OnFinally> tcf=new Stack<OnFinally>(); 169 private int currentTag; 170 private int line; 171 private BytecodeContext root; 172 private boolean writeLog; 173 private Stack<OnFinally> insideFinallies=new Stack<OnFinally>(); 174 175 //private static BytecodeContext staticConstr; 176 177 public void pushOnFinally(OnFinally onFinally) { 178 tcf.push(onFinally); 179 } 180 public void popOnFinally() { 181 tcf.pop(); 182 } 183 184 /*public void pushTryCatchFinallyData(TryCatchFinallyData data) { 185 tcf.push(data); 186 } 187 public void popTryCatchFinallyData() { 188 tcf.pop(); 189 }*/ 190 191 public Stack<OnFinally> getOnFinallyStack() { 192 return tcf; 193 } 194 195 /** 196 * @return the method 197 */ 198 public Method getMethod() { 199 return method; 200 } 201 202 /** 203 * @return the doSubFunctions 204 */ 205 public boolean doSubFunctions() { 206 return doSubFunctions; 207 } 208 209 /** 210 * @param doSubFunctions the doSubFunctions to set 211 * @return 212 */ 213 public boolean changeDoSubFunctions(boolean doSubFunctions) { 214 boolean old=this.doSubFunctions; 215 this.doSubFunctions = doSubFunctions; 216 return old; 217 } 218 219 /** 220 * @return the currentTag 221 */ 222 public int getCurrentTag() { 223 return currentTag; 224 } 225 226 /** 227 * @param currentTag the currentTag to set 228 */ 229 public void setCurrentTag(int currentTag) { 230 this.currentTag = currentTag; 231 } 232 233 public BytecodeContext getStaticConstructor() { 234 return staticConstr; 235 } 236 public BytecodeContext getConstructor() { 237 return constr; 238 } 239 240 public void visitLineNumber(int line) { 241 this.line=line; 242 getAdapter().visitLineNumber(line,getAdapter().mark()); 243 } 244 245 public int getLine() { 246 return line; 247 } 248 249 public BytecodeContext getRoot() { 250 return root; 251 } 252 public void setRoot(BytecodeContext root) { 253 this.root= root; 254 } 255 256 public boolean writeLog() { 257 return this.writeLog; 258 } 259 260 public Page getPage() { 261 return page; 262 } 263 264 public boolean getSupressWSbeforeArg(){ 265 return suppressWSbeforeArg; 266 } 267 268 public boolean getOutput() { 269 return output; 270 } 271 272 public PageSource getPageSource() { 273 return source; 274 } 275 276 public void finallyPush(OnFinally onf) { 277 insideFinallies.push(onf); 278 } 279 280 public OnFinally finallyPop() { 281 return insideFinallies.pop(); 282 } 283 284 285 public boolean insideFinally(OnFinally onf) { 286 Iterator<OnFinally> it = insideFinallies.iterator(); 287 while(it.hasNext()){ 288 if(it.next()==onf) return true; 289 } 290 return false; 291 } 292 293}